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