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