1 /** @file 2 Decode a hard disk partitioned with the GPT scheme in the UEFI 2.0 3 specification. 4 5 Caution: This file requires additional review when modified. 6 This driver will have external input - disk partition. 7 This external input must be validated carefully to avoid security issue like 8 buffer overflow, integer overflow. 9 10 PartitionInstallGptChildHandles() routine will read disk partition content and 11 do basic validation before PartitionInstallChildHandle(). 12 13 PartitionValidGptTable(), PartitionCheckGptEntry() routine will accept disk 14 partition content and validate the GPT table and GPT entry. 15 16 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR> 17 This program and the accompanying materials 18 are licensed and made available under the terms and conditions of the BSD License 19 which accompanies this distribution. The full text of the license may be found at 20 http://opensource.org/licenses/bsd-license.php 21 22 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 23 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 24 25 **/ 26 27 28 #include "Partition.h" 29 30 /** 31 Install child handles if the Handle supports GPT partition structure. 32 33 Caution: This function may receive untrusted input. 34 The GPT partition table header is external input, so this routine 35 will do basic validation for GPT partition table header before return. 36 37 @param[in] BlockIo Parent BlockIo interface. 38 @param[in] DiskIo Disk Io protocol. 39 @param[in] Lba The starting Lba of the Partition Table 40 @param[out] PartHeader Stores the partition table that is read 41 42 @retval TRUE The partition table is valid 43 @retval FALSE The partition table is not valid 44 45 **/ 46 BOOLEAN 47 PartitionValidGptTable ( 48 IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 49 IN EFI_DISK_IO_PROTOCOL *DiskIo, 50 IN EFI_LBA Lba, 51 OUT EFI_PARTITION_TABLE_HEADER *PartHeader 52 ); 53 54 /** 55 Check if the CRC field in the Partition table header is valid 56 for Partition entry array. 57 58 @param[in] BlockIo Parent BlockIo interface 59 @param[in] DiskIo Disk Io Protocol. 60 @param[in] PartHeader Partition table header structure 61 62 @retval TRUE the CRC is valid 63 @retval FALSE the CRC is invalid 64 65 **/ 66 BOOLEAN 67 PartitionCheckGptEntryArrayCRC ( 68 IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 69 IN EFI_DISK_IO_PROTOCOL *DiskIo, 70 IN EFI_PARTITION_TABLE_HEADER *PartHeader 71 ); 72 73 74 /** 75 Restore Partition Table to its alternate place 76 (Primary -> Backup or Backup -> Primary). 77 78 @param[in] BlockIo Parent BlockIo interface. 79 @param[in] DiskIo Disk Io Protocol. 80 @param[in] PartHeader Partition table header structure. 81 82 @retval TRUE Restoring succeeds 83 @retval FALSE Restoring failed 84 85 **/ 86 BOOLEAN 87 PartitionRestoreGptTable ( 88 IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 89 IN EFI_DISK_IO_PROTOCOL *DiskIo, 90 IN EFI_PARTITION_TABLE_HEADER *PartHeader 91 ); 92 93 94 /** 95 This routine will check GPT partition entry and return entry status. 96 97 Caution: This function may receive untrusted input. 98 The GPT partition entry is external input, so this routine 99 will do basic validation for GPT partition entry and report status. 100 101 @param[in] PartHeader Partition table header structure 102 @param[in] PartEntry The partition entry array 103 @param[out] PEntryStatus the partition entry status array 104 recording the status of each partition 105 106 **/ 107 VOID 108 PartitionCheckGptEntry ( 109 IN EFI_PARTITION_TABLE_HEADER *PartHeader, 110 IN EFI_PARTITION_ENTRY *PartEntry, 111 OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus 112 ); 113 114 115 /** 116 Checks the CRC32 value in the table header. 117 118 @param MaxSize Max Size limit 119 @param Size The size of the table 120 @param Hdr Table to check 121 122 @return TRUE CRC Valid 123 @return FALSE CRC Invalid 124 125 **/ 126 BOOLEAN 127 PartitionCheckCrcAltSize ( 128 IN UINTN MaxSize, 129 IN UINTN Size, 130 IN OUT EFI_TABLE_HEADER *Hdr 131 ); 132 133 134 /** 135 Checks the CRC32 value in the table header. 136 137 @param MaxSize Max Size limit 138 @param Hdr Table to check 139 140 @return TRUE CRC Valid 141 @return FALSE CRC Invalid 142 143 **/ 144 BOOLEAN 145 PartitionCheckCrc ( 146 IN UINTN MaxSize, 147 IN OUT EFI_TABLE_HEADER *Hdr 148 ); 149 150 151 /** 152 Updates the CRC32 value in the table header. 153 154 @param Size The size of the table 155 @param Hdr Table to update 156 157 **/ 158 VOID 159 PartitionSetCrcAltSize ( 160 IN UINTN Size, 161 IN OUT EFI_TABLE_HEADER *Hdr 162 ); 163 164 165 /** 166 Updates the CRC32 value in the table header. 167 168 @param Hdr Table to update 169 170 **/ 171 VOID 172 PartitionSetCrc ( 173 IN OUT EFI_TABLE_HEADER *Hdr 174 ); 175 176 /** 177 Install child handles if the Handle supports GPT partition structure. 178 179 Caution: This function may receive untrusted input. 180 The GPT partition table is external input, so this routine 181 will do basic validation for GPT partition table before install 182 child handle for each GPT partition. 183 184 @param[in] This Calling context. 185 @param[in] Handle Parent Handle. 186 @param[in] DiskIo Parent DiskIo interface. 187 @param[in] DiskIo2 Parent DiskIo2 interface. 188 @param[in] BlockIo Parent BlockIo interface. 189 @param[in] BlockIo2 Parent BlockIo2 interface. 190 @param[in] DevicePath Parent Device Path. 191 192 @retval EFI_SUCCESS Valid GPT disk. 193 @retval EFI_MEDIA_CHANGED Media changed Detected. 194 @retval other Not a valid GPT disk. 195 196 **/ 197 EFI_STATUS 198 PartitionInstallGptChildHandles ( 199 IN EFI_DRIVER_BINDING_PROTOCOL *This, 200 IN EFI_HANDLE Handle, 201 IN EFI_DISK_IO_PROTOCOL *DiskIo, 202 IN EFI_DISK_IO2_PROTOCOL *DiskIo2, 203 IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 204 IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, 205 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath 206 ) 207 { 208 EFI_STATUS Status; 209 UINT32 BlockSize; 210 EFI_LBA LastBlock; 211 MASTER_BOOT_RECORD *ProtectiveMbr; 212 EFI_PARTITION_TABLE_HEADER *PrimaryHeader; 213 EFI_PARTITION_TABLE_HEADER *BackupHeader; 214 EFI_PARTITION_ENTRY *PartEntry; 215 EFI_PARTITION_ENTRY *Entry; 216 EFI_PARTITION_ENTRY_STATUS *PEntryStatus; 217 UINTN Index; 218 EFI_STATUS GptValidStatus; 219 HARDDRIVE_DEVICE_PATH HdDev; 220 UINT32 MediaId; 221 222 ProtectiveMbr = NULL; 223 PrimaryHeader = NULL; 224 BackupHeader = NULL; 225 PartEntry = NULL; 226 PEntryStatus = NULL; 227 228 BlockSize = BlockIo->Media->BlockSize; 229 LastBlock = BlockIo->Media->LastBlock; 230 MediaId = BlockIo->Media->MediaId; 231 232 DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize)); 233 DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock)); 234 235 GptValidStatus = EFI_NOT_FOUND; 236 237 // 238 // Allocate a buffer for the Protective MBR 239 // 240 ProtectiveMbr = AllocatePool (BlockSize); 241 if (ProtectiveMbr == NULL) { 242 return EFI_NOT_FOUND; 243 } 244 245 // 246 // Read the Protective MBR from LBA #0 247 // 248 Status = DiskIo->ReadDisk ( 249 DiskIo, 250 MediaId, 251 0, 252 BlockSize, 253 ProtectiveMbr 254 ); 255 if (EFI_ERROR (Status)) { 256 GptValidStatus = Status; 257 goto Done; 258 } 259 260 // 261 // Verify that the Protective MBR is valid 262 // 263 for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { 264 if (ProtectiveMbr->Partition[Index].BootIndicator == 0x00 && 265 ProtectiveMbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION && 266 UNPACK_UINT32 (ProtectiveMbr->Partition[Index].StartingLBA) == 1 267 ) { 268 break; 269 } 270 } 271 if (Index == MAX_MBR_PARTITIONS) { 272 goto Done; 273 } 274 275 // 276 // Allocate the GPT structures 277 // 278 PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); 279 if (PrimaryHeader == NULL) { 280 goto Done; 281 } 282 283 BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); 284 if (BackupHeader == NULL) { 285 goto Done; 286 } 287 288 // 289 // Check primary and backup partition tables 290 // 291 if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) { 292 DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n")); 293 294 if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) { 295 DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n")); 296 goto Done; 297 } else { 298 DEBUG ((EFI_D_INFO, " Valid backup partition table\n")); 299 DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n")); 300 if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) { 301 DEBUG ((EFI_D_INFO, " Restore primary partition table error\n")); 302 } 303 304 if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) { 305 DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); 306 } 307 } 308 } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { 309 DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n")); 310 DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n")); 311 if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) { 312 DEBUG ((EFI_D_INFO, " Restore backup partition table error\n")); 313 } 314 315 if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { 316 DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); 317 } 318 319 } 320 321 DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n")); 322 323 // 324 // Read the EFI Partition Entries 325 // 326 PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); 327 if (PartEntry == NULL) { 328 DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); 329 goto Done; 330 } 331 332 Status = DiskIo->ReadDisk ( 333 DiskIo, 334 MediaId, 335 MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize), 336 PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry), 337 PartEntry 338 ); 339 if (EFI_ERROR (Status)) { 340 GptValidStatus = Status; 341 DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk error\n")); 342 goto Done; 343 } 344 345 DEBUG ((EFI_D_INFO, " Partition entries read block success\n")); 346 347 DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries)); 348 349 PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS)); 350 if (PEntryStatus == NULL) { 351 DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); 352 goto Done; 353 } 354 355 // 356 // Check the integrity of partition entries 357 // 358 PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus); 359 360 // 361 // If we got this far the GPT layout of the disk is valid and we should return true 362 // 363 GptValidStatus = EFI_SUCCESS; 364 365 // 366 // Create child device handles 367 // 368 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { 369 Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index * PrimaryHeader->SizeOfPartitionEntry); 370 if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid) || 371 PEntryStatus[Index].OutOfRange || 372 PEntryStatus[Index].Overlap || 373 PEntryStatus[Index].OsSpecific 374 ) { 375 // 376 // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific 377 // partition Entries 378 // 379 continue; 380 } 381 382 ZeroMem (&HdDev, sizeof (HdDev)); 383 HdDev.Header.Type = MEDIA_DEVICE_PATH; 384 HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; 385 SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); 386 387 HdDev.PartitionNumber = (UINT32) Index + 1; 388 HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; 389 HdDev.SignatureType = SIGNATURE_TYPE_GUID; 390 HdDev.PartitionStart = Entry->StartingLBA; 391 HdDev.PartitionSize = Entry->EndingLBA - Entry->StartingLBA + 1; 392 CopyMem (HdDev.Signature, &Entry->UniquePartitionGUID, sizeof (EFI_GUID)); 393 394 DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index)); 395 DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart)); 396 DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) Entry->EndingLBA)); 397 DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize)); 398 DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (Entry->StartingLBA, BlockSize))); 399 DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (Entry->EndingLBA, BlockSize))); 400 401 Status = PartitionInstallChildHandle ( 402 This, 403 Handle, 404 DiskIo, 405 DiskIo2, 406 BlockIo, 407 BlockIo2, 408 DevicePath, 409 (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, 410 Entry->StartingLBA, 411 Entry->EndingLBA, 412 BlockSize, 413 CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid) 414 ); 415 } 416 417 DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n")); 418 419 Done: 420 if (ProtectiveMbr != NULL) { 421 FreePool (ProtectiveMbr); 422 } 423 if (PrimaryHeader != NULL) { 424 FreePool (PrimaryHeader); 425 } 426 if (BackupHeader != NULL) { 427 FreePool (BackupHeader); 428 } 429 if (PartEntry != NULL) { 430 FreePool (PartEntry); 431 } 432 if (PEntryStatus != NULL) { 433 FreePool (PEntryStatus); 434 } 435 436 return GptValidStatus; 437 } 438 439 /** 440 This routine will read GPT partition table header and return it. 441 442 Caution: This function may receive untrusted input. 443 The GPT partition table header is external input, so this routine 444 will do basic validation for GPT partition table header before return. 445 446 @param[in] BlockIo Parent BlockIo interface. 447 @param[in] DiskIo Disk Io protocol. 448 @param[in] Lba The starting Lba of the Partition Table 449 @param[out] PartHeader Stores the partition table that is read 450 451 @retval TRUE The partition table is valid 452 @retval FALSE The partition table is not valid 453 454 **/ 455 BOOLEAN 456 PartitionValidGptTable ( 457 IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 458 IN EFI_DISK_IO_PROTOCOL *DiskIo, 459 IN EFI_LBA Lba, 460 OUT EFI_PARTITION_TABLE_HEADER *PartHeader 461 ) 462 { 463 EFI_STATUS Status; 464 UINT32 BlockSize; 465 EFI_PARTITION_TABLE_HEADER *PartHdr; 466 UINT32 MediaId; 467 468 BlockSize = BlockIo->Media->BlockSize; 469 MediaId = BlockIo->Media->MediaId; 470 PartHdr = AllocateZeroPool (BlockSize); 471 472 if (PartHdr == NULL) { 473 DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); 474 return FALSE; 475 } 476 // 477 // Read the EFI Partition Table Header 478 // 479 Status = DiskIo->ReadDisk ( 480 DiskIo, 481 MediaId, 482 MultU64x32 (Lba, BlockSize), 483 BlockSize, 484 PartHdr 485 ); 486 if (EFI_ERROR (Status)) { 487 FreePool (PartHdr); 488 return FALSE; 489 } 490 491 if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) || 492 !PartitionCheckCrc (BlockSize, &PartHdr->Header) || 493 PartHdr->MyLBA != Lba || 494 (PartHdr->SizeOfPartitionEntry < sizeof (EFI_PARTITION_ENTRY)) 495 ) { 496 DEBUG ((EFI_D_INFO, "Invalid efi partition table header\n")); 497 FreePool (PartHdr); 498 return FALSE; 499 } 500 501 // 502 // Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow. 503 // 504 if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) { 505 FreePool (PartHdr); 506 return FALSE; 507 } 508 509 CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER)); 510 if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) { 511 FreePool (PartHdr); 512 return FALSE; 513 } 514 515 DEBUG ((EFI_D_INFO, " Valid efi partition table header\n")); 516 FreePool (PartHdr); 517 return TRUE; 518 } 519 520 /** 521 Check if the CRC field in the Partition table header is valid 522 for Partition entry array. 523 524 @param[in] BlockIo Parent BlockIo interface 525 @param[in] DiskIo Disk Io Protocol. 526 @param[in] PartHeader Partition table header structure 527 528 @retval TRUE the CRC is valid 529 @retval FALSE the CRC is invalid 530 531 **/ 532 BOOLEAN 533 PartitionCheckGptEntryArrayCRC ( 534 IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 535 IN EFI_DISK_IO_PROTOCOL *DiskIo, 536 IN EFI_PARTITION_TABLE_HEADER *PartHeader 537 ) 538 { 539 EFI_STATUS Status; 540 UINT8 *Ptr; 541 UINT32 Crc; 542 UINTN Size; 543 544 // 545 // Read the EFI Partition Entries 546 // 547 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); 548 if (Ptr == NULL) { 549 DEBUG ((EFI_D_ERROR, " Allocate pool error\n")); 550 return FALSE; 551 } 552 553 Status = DiskIo->ReadDisk ( 554 DiskIo, 555 BlockIo->Media->MediaId, 556 MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), 557 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, 558 Ptr 559 ); 560 if (EFI_ERROR (Status)) { 561 FreePool (Ptr); 562 return FALSE; 563 } 564 565 Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; 566 567 Status = gBS->CalculateCrc32 (Ptr, Size, &Crc); 568 if (EFI_ERROR (Status)) { 569 DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n")); 570 FreePool (Ptr); 571 return FALSE; 572 } 573 574 FreePool (Ptr); 575 576 return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc); 577 } 578 579 580 /** 581 Restore Partition Table to its alternate place 582 (Primary -> Backup or Backup -> Primary). 583 584 @param[in] BlockIo Parent BlockIo interface. 585 @param[in] DiskIo Disk Io Protocol. 586 @param[in] PartHeader Partition table header structure. 587 588 @retval TRUE Restoring succeeds 589 @retval FALSE Restoring failed 590 591 **/ 592 BOOLEAN 593 PartitionRestoreGptTable ( 594 IN EFI_BLOCK_IO_PROTOCOL *BlockIo, 595 IN EFI_DISK_IO_PROTOCOL *DiskIo, 596 IN EFI_PARTITION_TABLE_HEADER *PartHeader 597 ) 598 { 599 EFI_STATUS Status; 600 UINTN BlockSize; 601 EFI_PARTITION_TABLE_HEADER *PartHdr; 602 EFI_LBA PEntryLBA; 603 UINT8 *Ptr; 604 UINT32 MediaId; 605 606 PartHdr = NULL; 607 Ptr = NULL; 608 609 BlockSize = BlockIo->Media->BlockSize; 610 MediaId = BlockIo->Media->MediaId; 611 612 PartHdr = AllocateZeroPool (BlockSize); 613 614 if (PartHdr == NULL) { 615 DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); 616 return FALSE; 617 } 618 619 PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \ 620 (PartHeader->LastUsableLBA + 1) : \ 621 (PRIMARY_PART_HEADER_LBA + 1); 622 623 CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER)); 624 625 PartHdr->MyLBA = PartHeader->AlternateLBA; 626 PartHdr->AlternateLBA = PartHeader->MyLBA; 627 PartHdr->PartitionEntryLBA = PEntryLBA; 628 PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr); 629 630 Status = DiskIo->WriteDisk ( 631 DiskIo, 632 MediaId, 633 MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize), 634 BlockSize, 635 PartHdr 636 ); 637 if (EFI_ERROR (Status)) { 638 goto Done; 639 } 640 641 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); 642 if (Ptr == NULL) { 643 DEBUG ((EFI_D_ERROR, " Allocate pool error\n")); 644 Status = EFI_OUT_OF_RESOURCES; 645 goto Done; 646 } 647 648 Status = DiskIo->ReadDisk ( 649 DiskIo, 650 MediaId, 651 MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize), 652 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, 653 Ptr 654 ); 655 if (EFI_ERROR (Status)) { 656 goto Done; 657 } 658 659 Status = DiskIo->WriteDisk ( 660 DiskIo, 661 MediaId, 662 MultU64x32(PEntryLBA, (UINT32) BlockSize), 663 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, 664 Ptr 665 ); 666 667 Done: 668 FreePool (PartHdr); 669 670 if (Ptr != NULL) { 671 FreePool (Ptr); 672 } 673 674 if (EFI_ERROR (Status)) { 675 return FALSE; 676 } 677 678 return TRUE; 679 } 680 681 /** 682 This routine will check GPT partition entry and return entry status. 683 684 Caution: This function may receive untrusted input. 685 The GPT partition entry is external input, so this routine 686 will do basic validation for GPT partition entry and report status. 687 688 @param[in] PartHeader Partition table header structure 689 @param[in] PartEntry The partition entry array 690 @param[out] PEntryStatus the partition entry status array 691 recording the status of each partition 692 693 **/ 694 VOID 695 PartitionCheckGptEntry ( 696 IN EFI_PARTITION_TABLE_HEADER *PartHeader, 697 IN EFI_PARTITION_ENTRY *PartEntry, 698 OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus 699 ) 700 { 701 EFI_LBA StartingLBA; 702 EFI_LBA EndingLBA; 703 EFI_PARTITION_ENTRY *Entry; 704 UINTN Index1; 705 UINTN Index2; 706 707 DEBUG ((EFI_D_INFO, " start check partition entries\n")); 708 for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) { 709 Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index1 * PartHeader->SizeOfPartitionEntry); 710 if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { 711 continue; 712 } 713 714 StartingLBA = Entry->StartingLBA; 715 EndingLBA = Entry->EndingLBA; 716 if (StartingLBA > EndingLBA || 717 StartingLBA < PartHeader->FirstUsableLBA || 718 StartingLBA > PartHeader->LastUsableLBA || 719 EndingLBA < PartHeader->FirstUsableLBA || 720 EndingLBA > PartHeader->LastUsableLBA 721 ) { 722 PEntryStatus[Index1].OutOfRange = TRUE; 723 continue; 724 } 725 726 if ((Entry->Attributes & BIT1) != 0) { 727 // 728 // If Bit 1 is set, this indicate that this is an OS specific GUID partition. 729 // 730 PEntryStatus[Index1].OsSpecific = TRUE; 731 } 732 733 for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) { 734 Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index2 * PartHeader->SizeOfPartitionEntry); 735 if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { 736 continue; 737 } 738 739 if (Entry->EndingLBA >= StartingLBA && Entry->StartingLBA <= EndingLBA) { 740 // 741 // This region overlaps with the Index1'th region 742 // 743 PEntryStatus[Index1].Overlap = TRUE; 744 PEntryStatus[Index2].Overlap = TRUE; 745 continue; 746 } 747 } 748 } 749 750 DEBUG ((EFI_D_INFO, " End check partition entries\n")); 751 } 752 753 754 /** 755 Updates the CRC32 value in the table header. 756 757 @param Hdr Table to update 758 759 **/ 760 VOID 761 PartitionSetCrc ( 762 IN OUT EFI_TABLE_HEADER *Hdr 763 ) 764 { 765 PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr); 766 } 767 768 769 /** 770 Updates the CRC32 value in the table header. 771 772 @param Size The size of the table 773 @param Hdr Table to update 774 775 **/ 776 VOID 777 PartitionSetCrcAltSize ( 778 IN UINTN Size, 779 IN OUT EFI_TABLE_HEADER *Hdr 780 ) 781 { 782 UINT32 Crc; 783 784 Hdr->CRC32 = 0; 785 gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc); 786 Hdr->CRC32 = Crc; 787 } 788 789 790 /** 791 Checks the CRC32 value in the table header. 792 793 @param MaxSize Max Size limit 794 @param Hdr Table to check 795 796 @return TRUE CRC Valid 797 @return FALSE CRC Invalid 798 799 **/ 800 BOOLEAN 801 PartitionCheckCrc ( 802 IN UINTN MaxSize, 803 IN OUT EFI_TABLE_HEADER *Hdr 804 ) 805 { 806 return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr); 807 } 808 809 810 /** 811 Checks the CRC32 value in the table header. 812 813 @param MaxSize Max Size limit 814 @param Size The size of the table 815 @param Hdr Table to check 816 817 @return TRUE CRC Valid 818 @return FALSE CRC Invalid 819 820 **/ 821 BOOLEAN 822 PartitionCheckCrcAltSize ( 823 IN UINTN MaxSize, 824 IN UINTN Size, 825 IN OUT EFI_TABLE_HEADER *Hdr 826 ) 827 { 828 UINT32 Crc; 829 UINT32 OrgCrc; 830 EFI_STATUS Status; 831 832 Crc = 0; 833 834 if (Size == 0) { 835 // 836 // If header size is 0 CRC will pass so return FALSE here 837 // 838 return FALSE; 839 } 840 841 if ((MaxSize != 0) && (Size > MaxSize)) { 842 DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n")); 843 return FALSE; 844 } 845 // 846 // clear old crc from header 847 // 848 OrgCrc = Hdr->CRC32; 849 Hdr->CRC32 = 0; 850 851 Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc); 852 if (EFI_ERROR (Status)) { 853 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n")); 854 return FALSE; 855 } 856 // 857 // set results 858 // 859 Hdr->CRC32 = Crc; 860 861 // 862 // return status 863 // 864 DEBUG_CODE_BEGIN (); 865 if (OrgCrc != Crc) { 866 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n")); 867 } 868 DEBUG_CODE_END (); 869 870 return (BOOLEAN) (OrgCrc == Crc); 871 } 872