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