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