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