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