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