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