]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
Update the copyright notice format
[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. All rights reserved.<BR>
6 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 PEntryStatus[Index].OsSpecific
344 ) {
345 //
346 // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific
347 // partition Entries
348 //
349 continue;
350 }
351
352 ZeroMem (&HdDev, sizeof (HdDev));
353 HdDev.Header.Type = MEDIA_DEVICE_PATH;
354 HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;
355 SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));
356
357 HdDev.PartitionNumber = (UINT32) Index + 1;
358 HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;
359 HdDev.SignatureType = SIGNATURE_TYPE_GUID;
360 HdDev.PartitionStart = PartEntry[Index].StartingLBA;
361 HdDev.PartitionSize = PartEntry[Index].EndingLBA - PartEntry[Index].StartingLBA + 1;
362 CopyMem (HdDev.Signature, &PartEntry[Index].UniquePartitionGUID, sizeof (EFI_GUID));
363
364 DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index));
365 DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart));
366 DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) PartEntry[Index].EndingLBA));
367 DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize));
368 DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (PartEntry[Index].StartingLBA, BlockSize)));
369 DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (PartEntry[Index].EndingLBA, BlockSize)));
370
371 Status = PartitionInstallChildHandle (
372 This,
373 Handle,
374 DiskIo,
375 BlockIo,
376 DevicePath,
377 (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,
378 PartEntry[Index].StartingLBA,
379 PartEntry[Index].EndingLBA,
380 BlockSize,
381 CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)
382 );
383 }
384
385 DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));
386
387 Done:
388 if (ProtectiveMbr != NULL) {
389 FreePool (ProtectiveMbr);
390 }
391 if (PrimaryHeader != NULL) {
392 FreePool (PrimaryHeader);
393 }
394 if (BackupHeader != NULL) {
395 FreePool (BackupHeader);
396 }
397 if (PartEntry != NULL) {
398 FreePool (PartEntry);
399 }
400 if (PEntryStatus != NULL) {
401 FreePool (PEntryStatus);
402 }
403
404 return GptValidStatus;
405 }
406
407
408 /**
409 Install child handles if the Handle supports GPT partition structure.
410
411 @param[in] BlockIo Parent BlockIo interface
412 @param[in] DiskIo Disk Io protocol.
413 @param[in] Lba The starting Lba of the Partition Table
414 @param[out] PartHeader Stores the partition table that is read
415
416 @retval TRUE The partition table is valid
417 @retval FALSE The partition table is not valid
418
419 **/
420 BOOLEAN
421 PartitionValidGptTable (
422 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
423 IN EFI_DISK_IO_PROTOCOL *DiskIo,
424 IN EFI_LBA Lba,
425 OUT EFI_PARTITION_TABLE_HEADER *PartHeader
426 )
427 {
428 EFI_STATUS Status;
429 UINT32 BlockSize;
430 EFI_PARTITION_TABLE_HEADER *PartHdr;
431
432 BlockSize = BlockIo->Media->BlockSize;
433
434 PartHdr = AllocateZeroPool (BlockSize);
435
436 if (PartHdr == NULL) {
437 DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
438 return FALSE;
439 }
440 //
441 // Read the EFI Partition Table Header
442 //
443 Status = DiskIo->ReadDisk (
444 DiskIo,
445 BlockIo->Media->MediaId,
446 MultU64x32 (Lba, BlockSize),
447 BlockSize,
448 PartHdr
449 );
450 if (EFI_ERROR (Status)) {
451 FreePool (PartHdr);
452 return FALSE;
453 }
454
455 if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||
456 !PartitionCheckCrc (BlockSize, &PartHdr->Header) ||
457 PartHdr->MyLBA != Lba
458 ) {
459 DEBUG ((EFI_D_INFO, "Invalid efi partition table header\n"));
460 FreePool (PartHdr);
461 return FALSE;
462 }
463
464 CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));
465 if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {
466 FreePool (PartHdr);
467 return FALSE;
468 }
469
470 DEBUG ((EFI_D_INFO, " Valid efi partition table header\n"));
471 FreePool (PartHdr);
472 return TRUE;
473 }
474
475
476 /**
477 Check if the CRC field in the Partition table header is valid
478 for Partition entry array.
479
480 @param[in] BlockIo Parent BlockIo interface
481 @param[in] DiskIo Disk Io Protocol.
482 @param[in] PartHeader Partition table header structure
483
484 @retval TRUE the CRC is valid
485 @retval FALSE the CRC is invalid
486
487 **/
488 BOOLEAN
489 PartitionCheckGptEntryArrayCRC (
490 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
491 IN EFI_DISK_IO_PROTOCOL *DiskIo,
492 IN EFI_PARTITION_TABLE_HEADER *PartHeader
493 )
494 {
495 EFI_STATUS Status;
496 UINT8 *Ptr;
497 UINT32 Crc;
498 UINTN Size;
499
500 //
501 // Read the EFI Partition Entries
502 //
503 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
504 if (Ptr == NULL) {
505 DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
506 return FALSE;
507 }
508
509 Status = DiskIo->ReadDisk (
510 DiskIo,
511 BlockIo->Media->MediaId,
512 MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
513 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
514 Ptr
515 );
516 if (EFI_ERROR (Status)) {
517 FreePool (Ptr);
518 return FALSE;
519 }
520
521 Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;
522
523 Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);
524 if (EFI_ERROR (Status)) {
525 DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));
526 FreePool (Ptr);
527 return FALSE;
528 }
529
530 FreePool (Ptr);
531
532 return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc);
533 }
534
535
536 /**
537 Restore Partition Table to its alternate place
538 (Primary -> Backup or Backup -> Primary)
539
540 @param[in] BlockIo Parent BlockIo interface
541 @param[in] DiskIo Disk Io Protocol.
542 @param[in] PartHeader Partition table header structure
543
544 @retval TRUE Restoring succeeds
545 @retval FALSE Restoring failed
546
547 **/
548 BOOLEAN
549 PartitionRestoreGptTable (
550 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
551 IN EFI_DISK_IO_PROTOCOL *DiskIo,
552 IN EFI_PARTITION_TABLE_HEADER *PartHeader
553 )
554 {
555 EFI_STATUS Status;
556 UINTN BlockSize;
557 EFI_PARTITION_TABLE_HEADER *PartHdr;
558 EFI_LBA PEntryLBA;
559 UINT8 *Ptr;
560
561 PartHdr = NULL;
562 Ptr = NULL;
563
564 BlockSize = BlockIo->Media->BlockSize;
565
566 PartHdr = AllocateZeroPool (BlockSize);
567
568 if (PartHdr == NULL) {
569 DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
570 return FALSE;
571 }
572
573 PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \
574 (PartHeader->LastUsableLBA + 1) : \
575 (PRIMARY_PART_HEADER_LBA + 1);
576
577 CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
578
579 PartHdr->MyLBA = PartHeader->AlternateLBA;
580 PartHdr->AlternateLBA = PartHeader->MyLBA;
581 PartHdr->PartitionEntryLBA = PEntryLBA;
582 PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);
583
584 Status = DiskIo->WriteDisk (
585 DiskIo,
586 BlockIo->Media->MediaId,
587 MultU64x32 (PartHdr->MyLBA, BlockIo->Media->BlockSize),
588 BlockSize,
589 PartHdr
590 );
591 if (EFI_ERROR (Status)) {
592 goto Done;
593 }
594
595 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
596 if (Ptr == NULL) {
597 DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
598 Status = EFI_OUT_OF_RESOURCES;
599 goto Done;
600 }
601
602 Status = DiskIo->ReadDisk (
603 DiskIo,
604 BlockIo->Media->MediaId,
605 MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
606 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
607 Ptr
608 );
609 if (EFI_ERROR (Status)) {
610 goto Done;
611 }
612
613 Status = DiskIo->WriteDisk (
614 DiskIo,
615 BlockIo->Media->MediaId,
616 MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),
617 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
618 Ptr
619 );
620
621 Done:
622 FreePool (PartHdr);
623
624 if (Ptr != NULL) {
625 FreePool (Ptr);
626 }
627
628 if (EFI_ERROR (Status)) {
629 return FALSE;
630 }
631
632 return TRUE;
633 }
634
635
636 /**
637 Restore Partition Table to its alternate place.
638 (Primary -> Backup or Backup -> Primary)
639
640 @param[in] PartHeader Partition table header structure
641 @param[in] PartEntry The partition entry array
642 @param[out] PEntryStatus the partition entry status array
643 recording the status of each partition
644
645 **/
646 VOID
647 PartitionCheckGptEntry (
648 IN EFI_PARTITION_TABLE_HEADER *PartHeader,
649 IN EFI_PARTITION_ENTRY *PartEntry,
650 OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
651 )
652 {
653 EFI_LBA StartingLBA;
654 EFI_LBA EndingLBA;
655 UINTN Index1;
656 UINTN Index2;
657 UINT64 Attributes;
658
659 DEBUG ((EFI_D_INFO, " start check partition entries\n"));
660 for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {
661 if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
662 continue;
663 }
664
665 StartingLBA = PartEntry[Index1].StartingLBA;
666 EndingLBA = PartEntry[Index1].EndingLBA;
667 if (StartingLBA > EndingLBA ||
668 StartingLBA < PartHeader->FirstUsableLBA ||
669 StartingLBA > PartHeader->LastUsableLBA ||
670 EndingLBA < PartHeader->FirstUsableLBA ||
671 EndingLBA > PartHeader->LastUsableLBA
672 ) {
673 PEntryStatus[Index1].OutOfRange = TRUE;
674 continue;
675 }
676
677 for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {
678
679 if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
680 continue;
681 }
682
683 if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {
684 //
685 // This region overlaps with the Index1'th region
686 //
687 PEntryStatus[Index1].Overlap = TRUE;
688 PEntryStatus[Index2].Overlap = TRUE;
689 continue;
690
691 }
692 }
693
694 Attributes = PartEntry[Index1].Attributes;
695 if ((Attributes & BIT1) != 0) {
696 //
697 // If Bit 1 is set, this indicate that this is an OS specific GUID partition.
698 //
699 PEntryStatus[Index1].OsSpecific = TRUE;
700 }
701 }
702
703 DEBUG ((EFI_D_INFO, " End check partition entries\n"));
704 }
705
706
707 /**
708 Updates the CRC32 value in the table header.
709
710 @param Hdr Table to update
711
712 **/
713 VOID
714 PartitionSetCrc (
715 IN OUT EFI_TABLE_HEADER *Hdr
716 )
717 {
718 PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);
719 }
720
721
722 /**
723 Updates the CRC32 value in the table header.
724
725 @param Size The size of the table
726 @param Hdr Table to update
727
728 **/
729 VOID
730 PartitionSetCrcAltSize (
731 IN UINTN Size,
732 IN OUT EFI_TABLE_HEADER *Hdr
733 )
734 {
735 UINT32 Crc;
736
737 Hdr->CRC32 = 0;
738 gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
739 Hdr->CRC32 = Crc;
740 }
741
742
743 /**
744 Checks the CRC32 value in the table header.
745
746 @param MaxSize Max Size limit
747 @param Hdr Table to check
748
749 @return TRUE CRC Valid
750 @return FALSE CRC Invalid
751
752 **/
753 BOOLEAN
754 PartitionCheckCrc (
755 IN UINTN MaxSize,
756 IN OUT EFI_TABLE_HEADER *Hdr
757 )
758 {
759 return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);
760 }
761
762
763 /**
764 Checks the CRC32 value in the table header.
765
766 @param MaxSize Max Size limit
767 @param Size The size of the table
768 @param Hdr Table to check
769
770 @return TRUE CRC Valid
771 @return FALSE CRC Invalid
772
773 **/
774 BOOLEAN
775 PartitionCheckCrcAltSize (
776 IN UINTN MaxSize,
777 IN UINTN Size,
778 IN OUT EFI_TABLE_HEADER *Hdr
779 )
780 {
781 UINT32 Crc;
782 UINT32 OrgCrc;
783 EFI_STATUS Status;
784
785 Crc = 0;
786
787 if (Size == 0) {
788 //
789 // If header size is 0 CRC will pass so return FALSE here
790 //
791 return FALSE;
792 }
793
794 if ((MaxSize != 0) && (Size > MaxSize)) {
795 DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));
796 return FALSE;
797 }
798 //
799 // clear old crc from header
800 //
801 OrgCrc = Hdr->CRC32;
802 Hdr->CRC32 = 0;
803
804 Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
805 if (EFI_ERROR (Status)) {
806 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));
807 return FALSE;
808 }
809 //
810 // set results
811 //
812 Hdr->CRC32 = Crc;
813
814 //
815 // return status
816 //
817 DEBUG_CODE_BEGIN ();
818 if (OrgCrc != Crc) {
819 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));
820 }
821 DEBUG_CODE_END ();
822
823 return (BOOLEAN) (OrgCrc == Crc);
824 }