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