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