]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
Add BlockIO2 Protocol.
[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] BlockIo2 Parent BlockIo2 interface.
485 @param[in] DiskIo Disk Io Protocol.
486 @param[in] PartHeader Partition table header structure
487
488 @retval TRUE the CRC is valid
489 @retval FALSE the CRC is invalid
490
491 **/
492 BOOLEAN
493 PartitionCheckGptEntryArrayCRC (
494 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
495 IN EFI_DISK_IO_PROTOCOL *DiskIo,
496 IN EFI_PARTITION_TABLE_HEADER *PartHeader
497 )
498 {
499 EFI_STATUS Status;
500 UINT8 *Ptr;
501 UINT32 Crc;
502 UINTN Size;
503
504 //
505 // Read the EFI Partition Entries
506 //
507 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
508 if (Ptr == NULL) {
509 DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
510 return FALSE;
511 }
512
513 Status = DiskIo->ReadDisk (
514 DiskIo,
515 BlockIo->Media->MediaId,
516 MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),
517 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
518 Ptr
519 );
520 if (EFI_ERROR (Status)) {
521 FreePool (Ptr);
522 return FALSE;
523 }
524
525 Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;
526
527 Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);
528 if (EFI_ERROR (Status)) {
529 DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));
530 FreePool (Ptr);
531 return FALSE;
532 }
533
534 FreePool (Ptr);
535
536 return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc);
537 }
538
539
540 /**
541 Restore Partition Table to its alternate place
542 (Primary -> Backup or Backup -> Primary).
543
544 @param[in] BlockIo Parent BlockIo interface.
545 @param[in] DiskIo Disk Io Protocol.
546 @param[in] PartHeader Partition table header structure.
547
548 @retval TRUE Restoring succeeds
549 @retval FALSE Restoring failed
550
551 **/
552 BOOLEAN
553 PartitionRestoreGptTable (
554 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,
555 IN EFI_DISK_IO_PROTOCOL *DiskIo,
556 IN EFI_PARTITION_TABLE_HEADER *PartHeader
557 )
558 {
559 EFI_STATUS Status;
560 UINTN BlockSize;
561 EFI_PARTITION_TABLE_HEADER *PartHdr;
562 EFI_LBA PEntryLBA;
563 UINT8 *Ptr;
564 UINT32 MediaId;
565
566 PartHdr = NULL;
567 Ptr = NULL;
568
569 BlockSize = BlockIo->Media->BlockSize;
570 MediaId = BlockIo->Media->MediaId;
571
572 PartHdr = AllocateZeroPool (BlockSize);
573
574 if (PartHdr == NULL) {
575 DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));
576 return FALSE;
577 }
578
579 PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \
580 (PartHeader->LastUsableLBA + 1) : \
581 (PRIMARY_PART_HEADER_LBA + 1);
582
583 CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));
584
585 PartHdr->MyLBA = PartHeader->AlternateLBA;
586 PartHdr->AlternateLBA = PartHeader->MyLBA;
587 PartHdr->PartitionEntryLBA = PEntryLBA;
588 PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);
589
590 Status = DiskIo->WriteDisk (
591 DiskIo,
592 MediaId,
593 MultU64x32 (PartHdr->MyLBA, (UINT32) BlockSize),
594 BlockSize,
595 PartHdr
596 );
597 if (EFI_ERROR (Status)) {
598 goto Done;
599 }
600
601 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);
602 if (Ptr == NULL) {
603 DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));
604 Status = EFI_OUT_OF_RESOURCES;
605 goto Done;
606 }
607
608 Status = DiskIo->ReadDisk (
609 DiskIo,
610 MediaId,
611 MultU64x32(PartHeader->PartitionEntryLBA, (UINT32) BlockSize),
612 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
613 Ptr
614 );
615 if (EFI_ERROR (Status)) {
616 goto Done;
617 }
618
619 Status = DiskIo->WriteDisk (
620 DiskIo,
621 MediaId,
622 MultU64x32(PEntryLBA, (UINT32) BlockSize),
623 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,
624 Ptr
625 );
626
627 Done:
628 FreePool (PartHdr);
629
630 if (Ptr != NULL) {
631 FreePool (Ptr);
632 }
633
634 if (EFI_ERROR (Status)) {
635 return FALSE;
636 }
637
638 return TRUE;
639 }
640
641
642 /**
643 Restore Partition Table to its alternate place.
644 (Primary -> Backup or Backup -> Primary)
645
646 @param[in] PartHeader Partition table header structure
647 @param[in] PartEntry The partition entry array
648 @param[out] PEntryStatus the partition entry status array
649 recording the status of each partition
650
651 **/
652 VOID
653 PartitionCheckGptEntry (
654 IN EFI_PARTITION_TABLE_HEADER *PartHeader,
655 IN EFI_PARTITION_ENTRY *PartEntry,
656 OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus
657 )
658 {
659 EFI_LBA StartingLBA;
660 EFI_LBA EndingLBA;
661 UINTN Index1;
662 UINTN Index2;
663 UINT64 Attributes;
664
665 DEBUG ((EFI_D_INFO, " start check partition entries\n"));
666 for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {
667 if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
668 continue;
669 }
670
671 StartingLBA = PartEntry[Index1].StartingLBA;
672 EndingLBA = PartEntry[Index1].EndingLBA;
673 if (StartingLBA > EndingLBA ||
674 StartingLBA < PartHeader->FirstUsableLBA ||
675 StartingLBA > PartHeader->LastUsableLBA ||
676 EndingLBA < PartHeader->FirstUsableLBA ||
677 EndingLBA > PartHeader->LastUsableLBA
678 ) {
679 PEntryStatus[Index1].OutOfRange = TRUE;
680 continue;
681 }
682
683 for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {
684
685 if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {
686 continue;
687 }
688
689 if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {
690 //
691 // This region overlaps with the Index1'th region
692 //
693 PEntryStatus[Index1].Overlap = TRUE;
694 PEntryStatus[Index2].Overlap = TRUE;
695 continue;
696
697 }
698 }
699
700 Attributes = PartEntry[Index1].Attributes;
701 if ((Attributes & BIT1) != 0) {
702 //
703 // If Bit 1 is set, this indicate that this is an OS specific GUID partition.
704 //
705 PEntryStatus[Index1].OsSpecific = TRUE;
706 }
707 }
708
709 DEBUG ((EFI_D_INFO, " End check partition entries\n"));
710 }
711
712
713 /**
714 Updates the CRC32 value in the table header.
715
716 @param Hdr Table to update
717
718 **/
719 VOID
720 PartitionSetCrc (
721 IN OUT EFI_TABLE_HEADER *Hdr
722 )
723 {
724 PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);
725 }
726
727
728 /**
729 Updates the CRC32 value in the table header.
730
731 @param Size The size of the table
732 @param Hdr Table to update
733
734 **/
735 VOID
736 PartitionSetCrcAltSize (
737 IN UINTN Size,
738 IN OUT EFI_TABLE_HEADER *Hdr
739 )
740 {
741 UINT32 Crc;
742
743 Hdr->CRC32 = 0;
744 gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
745 Hdr->CRC32 = Crc;
746 }
747
748
749 /**
750 Checks the CRC32 value in the table header.
751
752 @param MaxSize Max Size limit
753 @param Hdr Table to check
754
755 @return TRUE CRC Valid
756 @return FALSE CRC Invalid
757
758 **/
759 BOOLEAN
760 PartitionCheckCrc (
761 IN UINTN MaxSize,
762 IN OUT EFI_TABLE_HEADER *Hdr
763 )
764 {
765 return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);
766 }
767
768
769 /**
770 Checks the CRC32 value in the table header.
771
772 @param MaxSize Max Size limit
773 @param Size The size of the table
774 @param Hdr Table to check
775
776 @return TRUE CRC Valid
777 @return FALSE CRC Invalid
778
779 **/
780 BOOLEAN
781 PartitionCheckCrcAltSize (
782 IN UINTN MaxSize,
783 IN UINTN Size,
784 IN OUT EFI_TABLE_HEADER *Hdr
785 )
786 {
787 UINT32 Crc;
788 UINT32 OrgCrc;
789 EFI_STATUS Status;
790
791 Crc = 0;
792
793 if (Size == 0) {
794 //
795 // If header size is 0 CRC will pass so return FALSE here
796 //
797 return FALSE;
798 }
799
800 if ((MaxSize != 0) && (Size > MaxSize)) {
801 DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));
802 return FALSE;
803 }
804 //
805 // clear old crc from header
806 //
807 OrgCrc = Hdr->CRC32;
808 Hdr->CRC32 = 0;
809
810 Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);
811 if (EFI_ERROR (Status)) {
812 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));
813 return FALSE;
814 }
815 //
816 // set results
817 //
818 Hdr->CRC32 = Crc;
819
820 //
821 // return status
822 //
823 DEBUG_CODE_BEGIN ();
824 if (OrgCrc != Crc) {
825 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));
826 }
827 DEBUG_CODE_END ();
828
829 return (BOOLEAN) (OrgCrc == Crc);
830 }