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