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