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