]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
Update VfrCompiler to handle ideqvallist as the first opcode case. Per UEFI spec...
[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
ff61847d 192 EFI_STATUS GptValidStatus;\r
adbcbf8f 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
7df7393f 205 DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock));\r
adbcbf8f 206\r
ff61847d 207 GptValidStatus = EFI_NOT_FOUND;\r
adbcbf8f 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
ff61847d 228 GptValidStatus = Status;\r
adbcbf8f 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
adbcbf8f 250 if (BackupHeader == NULL) {\r
251 goto Done;\r
252 }\r
253\r
254 //\r
255 // Check primary and backup partition tables\r
256 //\r
257 if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) {\r
258 DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n"));\r
259\r
260 if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) {\r
261 DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n"));\r
262 goto Done;\r
263 } else {\r
264 DEBUG ((EFI_D_INFO, " Valid backup partition table\n"));\r
265 DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n"));\r
266 if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) {\r
267 DEBUG ((EFI_D_INFO, " Restore primary partition table error\n"));\r
268 }\r
269\r
270 if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) {\r
271 DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));\r
272 }\r
273 }\r
274 } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {\r
275 DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n"));\r
276 DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n"));\r
277 if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) {\r
278 DEBUG ((EFI_D_INFO, " Restore backup partition table error\n"));\r
279 }\r
280\r
281 if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) {\r
282 DEBUG ((EFI_D_INFO, " Restore backup partition table success\n"));\r
283 }\r
284\r
285 }\r
286\r
287 DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n"));\r
288\r
289 //\r
290 // Read the EFI Partition Entries\r
291 //\r
292 PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY));\r
293 if (PartEntry == NULL) {\r
294 DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
295 goto Done;\r
296 }\r
297\r
298 Status = DiskIo->ReadDisk (\r
299 DiskIo,\r
300 BlockIo->Media->MediaId,\r
301 MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize),\r
302 PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry),\r
303 PartEntry\r
304 );\r
305 if (EFI_ERROR (Status)) {\r
ff61847d 306 GptValidStatus = Status;\r
307 DEBUG ((EFI_D_ERROR, " Partition Entry ReadBlocks error\n"));\r
adbcbf8f 308 goto Done;\r
309 }\r
310\r
311 DEBUG ((EFI_D_INFO, " Partition entries read block success\n"));\r
312\r
313 DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries));\r
314\r
315 PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS));\r
316 if (PEntryStatus == NULL) {\r
317 DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
318 goto Done;\r
319 }\r
320\r
321 //\r
322 // Check the integrity of partition entries\r
323 //\r
324 PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus);\r
325\r
326 //\r
327 // If we got this far the GPT layout of the disk is valid and we should return true\r
328 //\r
ff61847d 329 GptValidStatus = EFI_SUCCESS;\r
adbcbf8f 330\r
331 //\r
332 // Create child device handles\r
333 //\r
334 for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) {\r
335 if (CompareGuid (&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeUnusedGuid) ||\r
336 PEntryStatus[Index].OutOfRange ||\r
337 PEntryStatus[Index].Overlap\r
338 ) {\r
339 //\r
340 // Don't use null EFI Partition Entries or Invalid Partition Entries\r
341 //\r
342 continue;\r
343 }\r
344\r
345 ZeroMem (&HdDev, sizeof (HdDev));\r
346 HdDev.Header.Type = MEDIA_DEVICE_PATH;\r
347 HdDev.Header.SubType = MEDIA_HARDDRIVE_DP;\r
348 SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev));\r
349\r
350 HdDev.PartitionNumber = (UINT32) Index + 1;\r
351 HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER;\r
352 HdDev.SignatureType = SIGNATURE_TYPE_GUID;\r
353 HdDev.PartitionStart = PartEntry[Index].StartingLBA;\r
354 HdDev.PartitionSize = PartEntry[Index].EndingLBA - PartEntry[Index].StartingLBA + 1;\r
355 CopyMem (HdDev.Signature, &PartEntry[Index].UniquePartitionGUID, sizeof (EFI_GUID));\r
356\r
ff61847d 357 DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index));\r
358 DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart));\r
359 DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) PartEntry[Index].EndingLBA));\r
360 DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize));\r
361 DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (PartEntry[Index].StartingLBA, BlockSize)));\r
362 DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (PartEntry[Index].EndingLBA, BlockSize)));\r
adbcbf8f 363\r
364 Status = PartitionInstallChildHandle (\r
365 This,\r
366 Handle,\r
367 DiskIo,\r
368 BlockIo,\r
369 DevicePath,\r
370 (EFI_DEVICE_PATH_PROTOCOL *) &HdDev,\r
371 PartEntry[Index].StartingLBA,\r
372 PartEntry[Index].EndingLBA,\r
373 BlockSize,\r
374 CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)\r
375 );\r
376 }\r
377\r
378 DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n"));\r
379\r
380Done:\r
381 if (ProtectiveMbr != NULL) {\r
382 FreePool (ProtectiveMbr);\r
383 }\r
384 if (PrimaryHeader != NULL) {\r
385 FreePool (PrimaryHeader);\r
386 }\r
387 if (BackupHeader != NULL) {\r
388 FreePool (BackupHeader);\r
389 }\r
390 if (PartEntry != NULL) {\r
391 FreePool (PartEntry);\r
392 }\r
393 if (PEntryStatus != NULL) {\r
394 FreePool (PEntryStatus);\r
395 }\r
396\r
ff61847d 397 return GptValidStatus;\r
adbcbf8f 398}\r
399\r
400\r
401/**\r
402 Install child handles if the Handle supports GPT partition structure.\r
403\r
404 @param[in] BlockIo Parent BlockIo interface\r
405 @param[in] DiskIo Disk Io protocol.\r
406 @param[in] Lba The starting Lba of the Partition Table\r
a8d0c20e 407 @param[out] PartHeader Stores the partition table that is read\r
adbcbf8f 408\r
409 @retval TRUE The partition table is valid\r
410 @retval FALSE The partition table is not valid\r
411\r
412**/\r
413BOOLEAN\r
414PartitionValidGptTable (\r
415 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
416 IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
417 IN EFI_LBA Lba,\r
418 OUT EFI_PARTITION_TABLE_HEADER *PartHeader\r
419 )\r
420{\r
421 EFI_STATUS Status;\r
422 UINT32 BlockSize;\r
423 EFI_PARTITION_TABLE_HEADER *PartHdr;\r
424\r
425 BlockSize = BlockIo->Media->BlockSize;\r
426\r
427 PartHdr = AllocateZeroPool (BlockSize);\r
428\r
429 if (PartHdr == NULL) {\r
430 DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
431 return FALSE;\r
432 }\r
433 //\r
434 // Read the EFI Partition Table Header\r
435 //\r
436 Status = BlockIo->ReadBlocks (\r
437 BlockIo,\r
438 BlockIo->Media->MediaId,\r
439 Lba,\r
440 BlockSize,\r
441 PartHdr\r
442 );\r
443 if (EFI_ERROR (Status)) {\r
444 FreePool (PartHdr);\r
445 return FALSE;\r
446 }\r
447\r
cd2d8468 448 if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||\r
adbcbf8f 449 !PartitionCheckCrc (BlockSize, &PartHdr->Header) ||\r
450 PartHdr->MyLBA != Lba\r
451 ) {\r
ff61847d 452 DEBUG ((EFI_D_INFO, "Invalid efi partition table header\n"));\r
adbcbf8f 453 FreePool (PartHdr);\r
454 return FALSE;\r
455 }\r
456\r
457 CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER));\r
458 if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) {\r
459 FreePool (PartHdr);\r
460 return FALSE;\r
461 }\r
462\r
463 DEBUG ((EFI_D_INFO, " Valid efi partition table header\n"));\r
464 FreePool (PartHdr);\r
465 return TRUE;\r
466}\r
467\r
468\r
469/**\r
470 Check if the CRC field in the Partition table header is valid\r
471 for Partition entry array.\r
472\r
473 @param[in] BlockIo Parent BlockIo interface\r
474 @param[in] DiskIo Disk Io Protocol.\r
475 @param[in] PartHeader Partition table header structure\r
476\r
477 @retval TRUE the CRC is valid\r
478 @retval FALSE the CRC is invalid\r
479\r
480**/\r
481BOOLEAN\r
482PartitionCheckGptEntryArrayCRC (\r
483 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
484 IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
485 IN EFI_PARTITION_TABLE_HEADER *PartHeader\r
486 )\r
487{\r
488 EFI_STATUS Status;\r
489 UINT8 *Ptr;\r
490 UINT32 Crc;\r
491 UINTN Size;\r
492\r
493 //\r
494 // Read the EFI Partition Entries\r
495 //\r
496 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);\r
497 if (Ptr == NULL) {\r
498 DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));\r
499 return FALSE;\r
500 }\r
501\r
502 Status = DiskIo->ReadDisk (\r
503 DiskIo,\r
504 BlockIo->Media->MediaId,\r
505 MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
506 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
507 Ptr\r
508 );\r
509 if (EFI_ERROR (Status)) {\r
510 FreePool (Ptr);\r
511 return FALSE;\r
512 }\r
513\r
514 Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry;\r
515\r
516 Status = gBS->CalculateCrc32 (Ptr, Size, &Crc);\r
517 if (EFI_ERROR (Status)) {\r
518 DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n"));\r
519 FreePool (Ptr);\r
520 return FALSE;\r
521 }\r
522\r
523 FreePool (Ptr);\r
524\r
525 return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc);\r
526}\r
527\r
528\r
529/**\r
530 Restore Partition Table to its alternate place\r
531 (Primary -> Backup or Backup -> Primary)\r
532\r
533 @param[in] BlockIo Parent BlockIo interface\r
534 @param[in] DiskIo Disk Io Protocol.\r
535 @param[in] PartHeader Partition table header structure\r
536\r
537 @retval TRUE Restoring succeeds\r
538 @retval FALSE Restoring failed\r
539\r
540**/\r
541BOOLEAN\r
542PartitionRestoreGptTable (\r
543 IN EFI_BLOCK_IO_PROTOCOL *BlockIo,\r
544 IN EFI_DISK_IO_PROTOCOL *DiskIo,\r
545 IN EFI_PARTITION_TABLE_HEADER *PartHeader\r
546 )\r
547{\r
548 EFI_STATUS Status;\r
549 UINTN BlockSize;\r
550 EFI_PARTITION_TABLE_HEADER *PartHdr;\r
551 EFI_LBA PEntryLBA;\r
552 UINT8 *Ptr;\r
553\r
554 PartHdr = NULL;\r
555 Ptr = NULL;\r
556\r
557 BlockSize = BlockIo->Media->BlockSize;\r
558\r
559 PartHdr = AllocateZeroPool (BlockSize);\r
560\r
561 if (PartHdr == NULL) {\r
562 DEBUG ((EFI_D_ERROR, "Allocate pool error\n"));\r
563 return FALSE;\r
564 }\r
565\r
566 PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \\r
567 (PartHeader->LastUsableLBA + 1) : \\r
568 (PRIMARY_PART_HEADER_LBA + 1);\r
569\r
570 CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER));\r
571\r
572 PartHdr->MyLBA = PartHeader->AlternateLBA;\r
573 PartHdr->AlternateLBA = PartHeader->MyLBA;\r
574 PartHdr->PartitionEntryLBA = PEntryLBA;\r
575 PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr);\r
576\r
577 Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartHdr->MyLBA, BlockSize, PartHdr);\r
578 if (EFI_ERROR (Status)) {\r
579 goto Done;\r
580 }\r
581\r
582 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);\r
583 if (Ptr == NULL) {\r
584 DEBUG ((EFI_D_ERROR, " Allocate pool effor\n"));\r
585 Status = EFI_OUT_OF_RESOURCES;\r
586 goto Done;\r
587 }\r
588\r
589 Status = DiskIo->ReadDisk (\r
590 DiskIo,\r
591 BlockIo->Media->MediaId,\r
592 MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
593 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
594 Ptr\r
595 );\r
596 if (EFI_ERROR (Status)) {\r
597 goto Done;\r
598 }\r
599\r
600 Status = DiskIo->WriteDisk (\r
601 DiskIo,\r
602 BlockIo->Media->MediaId,\r
603 MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),\r
604 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
605 Ptr\r
606 );\r
607\r
608Done:\r
609 FreePool (PartHdr);\r
ff61847d 610\r
611 if (Ptr != NULL) {\r
612 FreePool (Ptr);\r
613 }\r
adbcbf8f 614\r
615 if (EFI_ERROR (Status)) {\r
616 return FALSE;\r
617 }\r
618\r
619 return TRUE;\r
620}\r
621\r
622\r
623/**\r
ea7cb08c 624 Restore Partition Table to its alternate place.\r
adbcbf8f 625 (Primary -> Backup or Backup -> Primary)\r
626\r
627 @param[in] PartHeader Partition table header structure\r
628 @param[in] PartEntry The partition entry array\r
629 @param[out] PEntryStatus the partition entry status array \r
630 recording the status of each partition\r
a8d0c20e 631\r
adbcbf8f 632**/\r
633VOID\r
634PartitionCheckGptEntry (\r
635 IN EFI_PARTITION_TABLE_HEADER *PartHeader,\r
636 IN EFI_PARTITION_ENTRY *PartEntry,\r
637 OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus\r
638 )\r
639{\r
640 EFI_LBA StartingLBA;\r
641 EFI_LBA EndingLBA;\r
642 UINTN Index1;\r
643 UINTN Index2;\r
644\r
645 DEBUG ((EFI_D_INFO, " start check partition entries\n"));\r
646 for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {\r
647 if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
648 continue;\r
649 }\r
650\r
651 StartingLBA = PartEntry[Index1].StartingLBA;\r
652 EndingLBA = PartEntry[Index1].EndingLBA;\r
653 if (StartingLBA > EndingLBA ||\r
654 StartingLBA < PartHeader->FirstUsableLBA ||\r
655 StartingLBA > PartHeader->LastUsableLBA ||\r
656 EndingLBA < PartHeader->FirstUsableLBA ||\r
657 EndingLBA > PartHeader->LastUsableLBA\r
658 ) {\r
659 PEntryStatus[Index1].OutOfRange = TRUE;\r
660 continue;\r
661 }\r
662\r
663 for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {\r
664\r
665 if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
666 continue;\r
667 }\r
668\r
669 if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {\r
670 //\r
671 // This region overlaps with the Index1'th region\r
672 //\r
673 PEntryStatus[Index1].Overlap = TRUE;\r
674 PEntryStatus[Index2].Overlap = TRUE;\r
675 continue;\r
676\r
677 }\r
678 }\r
679 }\r
680\r
681 DEBUG ((EFI_D_INFO, " End check partition entries\n"));\r
682}\r
683\r
684\r
685/**\r
ea7cb08c 686 Updates the CRC32 value in the table header.\r
adbcbf8f 687\r
a8d0c20e 688 @param Hdr Table to update\r
adbcbf8f 689\r
690**/\r
691VOID\r
692PartitionSetCrc (\r
693 IN OUT EFI_TABLE_HEADER *Hdr\r
694 )\r
695{\r
696 PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);\r
697}\r
698\r
699\r
700/**\r
ea7cb08c 701 Updates the CRC32 value in the table header.\r
adbcbf8f 702\r
a8d0c20e 703 @param Size The size of the table\r
704 @param Hdr Table to update\r
adbcbf8f 705\r
706**/\r
707VOID\r
708PartitionSetCrcAltSize (\r
709 IN UINTN Size,\r
710 IN OUT EFI_TABLE_HEADER *Hdr\r
711 )\r
adbcbf8f 712{\r
713 UINT32 Crc;\r
714\r
715 Hdr->CRC32 = 0;\r
716 gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);\r
717 Hdr->CRC32 = Crc;\r
718}\r
719\r
720\r
721/**\r
ea7cb08c 722 Checks the CRC32 value in the table header.\r
adbcbf8f 723\r
a8d0c20e 724 @param MaxSize Max Size limit\r
725 @param Hdr Table to check\r
adbcbf8f 726\r
a8d0c20e 727 @return TRUE CRC Valid\r
728 @return FALSE CRC Invalid\r
adbcbf8f 729\r
730**/\r
731BOOLEAN\r
732PartitionCheckCrc (\r
733 IN UINTN MaxSize,\r
734 IN OUT EFI_TABLE_HEADER *Hdr\r
735 )\r
736{\r
737 return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);\r
738}\r
739\r
740\r
741/**\r
ea7cb08c 742 Checks the CRC32 value in the table header.\r
adbcbf8f 743\r
a8d0c20e 744 @param MaxSize Max Size limit\r
745 @param Size The size of the table\r
746 @param Hdr Table to check\r
adbcbf8f 747\r
748 @return TRUE CRC Valid\r
749 @return FALSE CRC Invalid\r
750\r
751**/\r
752BOOLEAN\r
753PartitionCheckCrcAltSize (\r
754 IN UINTN MaxSize,\r
755 IN UINTN Size,\r
756 IN OUT EFI_TABLE_HEADER *Hdr\r
757 )\r
758{\r
759 UINT32 Crc;\r
760 UINT32 OrgCrc;\r
761 EFI_STATUS Status;\r
762\r
763 Crc = 0;\r
764\r
765 if (Size == 0) {\r
766 //\r
767 // If header size is 0 CRC will pass so return FALSE here\r
768 //\r
769 return FALSE;\r
770 }\r
771\r
ea7cb08c 772 if ((MaxSize != 0) && (Size > MaxSize)) {\r
adbcbf8f 773 DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));\r
774 return FALSE;\r
775 }\r
776 //\r
777 // clear old crc from header\r
778 //\r
779 OrgCrc = Hdr->CRC32;\r
780 Hdr->CRC32 = 0;\r
781\r
782 Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);\r
783 if (EFI_ERROR (Status)) {\r
784 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));\r
785 return FALSE;\r
786 }\r
787 //\r
788 // set results\r
789 //\r
790 Hdr->CRC32 = Crc;\r
791\r
792 //\r
793 // return status\r
794 //\r
795 DEBUG_CODE_BEGIN ();\r
796 if (OrgCrc != Crc) {\r
797 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));\r
798 }\r
799 DEBUG_CODE_END ();\r
800\r
801 return (BOOLEAN) (OrgCrc == Crc);\r
802}\r