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