]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Disk/PartitionDxe/Gpt.c
Fix a potential issue to use FreePool() with NULL pointer.
[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
96f99e1d 220 Status = DiskIo->ReadDisk (\r
221 DiskIo,\r
222 BlockIo->Media->MediaId,\r
223 0,\r
224 BlockIo->Media->BlockSize,\r
225 ProtectiveMbr\r
226 );\r
adbcbf8f 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
7059dad9 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
adbcbf8f 305 if (EFI_ERROR (Status)) {\r
ff61847d 306 GptValidStatus = Status;\r
96f99e1d 307 DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk 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
96f99e1d 436 Status = DiskIo->ReadDisk (\r
437 DiskIo,\r
438 BlockIo->Media->MediaId,\r
7059dad9 439 MultU64x32 (Lba, BlockSize),\r
96f99e1d 440 BlockSize,\r
441 PartHdr\r
442 );\r
adbcbf8f 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
071b7221 577 Status = DiskIo->WriteDisk (\r
578 DiskIo,\r
579 BlockIo->Media->MediaId,\r
580 MultU64x32 (PartHdr->MyLBA, BlockIo->Media->BlockSize),\r
581 BlockSize,\r
582 PartHdr\r
583 );\r
adbcbf8f 584 if (EFI_ERROR (Status)) {\r
585 goto Done;\r
586 }\r
587\r
588 Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry);\r
589 if (Ptr == NULL) {\r
071b7221 590 DEBUG ((EFI_D_ERROR, " Allocate pool error\n"));\r
adbcbf8f 591 Status = EFI_OUT_OF_RESOURCES;\r
592 goto Done;\r
593 }\r
594\r
595 Status = DiskIo->ReadDisk (\r
596 DiskIo,\r
597 BlockIo->Media->MediaId,\r
598 MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize),\r
599 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
600 Ptr\r
601 );\r
602 if (EFI_ERROR (Status)) {\r
603 goto Done;\r
604 }\r
605\r
606 Status = DiskIo->WriteDisk (\r
607 DiskIo,\r
608 BlockIo->Media->MediaId,\r
609 MultU64x32(PEntryLBA, BlockIo->Media->BlockSize),\r
610 PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry,\r
611 Ptr\r
612 );\r
613\r
614Done:\r
615 FreePool (PartHdr);\r
ff61847d 616\r
617 if (Ptr != NULL) {\r
618 FreePool (Ptr);\r
619 }\r
adbcbf8f 620\r
621 if (EFI_ERROR (Status)) {\r
622 return FALSE;\r
623 }\r
624\r
625 return TRUE;\r
626}\r
627\r
628\r
629/**\r
ea7cb08c 630 Restore Partition Table to its alternate place.\r
adbcbf8f 631 (Primary -> Backup or Backup -> Primary)\r
632\r
633 @param[in] PartHeader Partition table header structure\r
634 @param[in] PartEntry The partition entry array\r
635 @param[out] PEntryStatus the partition entry status array \r
636 recording the status of each partition\r
a8d0c20e 637\r
adbcbf8f 638**/\r
639VOID\r
640PartitionCheckGptEntry (\r
641 IN EFI_PARTITION_TABLE_HEADER *PartHeader,\r
642 IN EFI_PARTITION_ENTRY *PartEntry,\r
643 OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus\r
644 )\r
645{\r
646 EFI_LBA StartingLBA;\r
647 EFI_LBA EndingLBA;\r
648 UINTN Index1;\r
649 UINTN Index2;\r
650\r
651 DEBUG ((EFI_D_INFO, " start check partition entries\n"));\r
652 for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) {\r
653 if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
654 continue;\r
655 }\r
656\r
657 StartingLBA = PartEntry[Index1].StartingLBA;\r
658 EndingLBA = PartEntry[Index1].EndingLBA;\r
659 if (StartingLBA > EndingLBA ||\r
660 StartingLBA < PartHeader->FirstUsableLBA ||\r
661 StartingLBA > PartHeader->LastUsableLBA ||\r
662 EndingLBA < PartHeader->FirstUsableLBA ||\r
663 EndingLBA > PartHeader->LastUsableLBA\r
664 ) {\r
665 PEntryStatus[Index1].OutOfRange = TRUE;\r
666 continue;\r
667 }\r
668\r
669 for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) {\r
670\r
671 if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
672 continue;\r
673 }\r
674\r
675 if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) {\r
676 //\r
677 // This region overlaps with the Index1'th region\r
678 //\r
679 PEntryStatus[Index1].Overlap = TRUE;\r
680 PEntryStatus[Index2].Overlap = TRUE;\r
681 continue;\r
682\r
683 }\r
684 }\r
685 }\r
686\r
687 DEBUG ((EFI_D_INFO, " End check partition entries\n"));\r
688}\r
689\r
690\r
691/**\r
ea7cb08c 692 Updates the CRC32 value in the table header.\r
adbcbf8f 693\r
a8d0c20e 694 @param Hdr Table to update\r
adbcbf8f 695\r
696**/\r
697VOID\r
698PartitionSetCrc (\r
699 IN OUT EFI_TABLE_HEADER *Hdr\r
700 )\r
701{\r
702 PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr);\r
703}\r
704\r
705\r
706/**\r
ea7cb08c 707 Updates the CRC32 value in the table header.\r
adbcbf8f 708\r
a8d0c20e 709 @param Size The size of the table\r
710 @param Hdr Table to update\r
adbcbf8f 711\r
712**/\r
713VOID\r
714PartitionSetCrcAltSize (\r
715 IN UINTN Size,\r
716 IN OUT EFI_TABLE_HEADER *Hdr\r
717 )\r
adbcbf8f 718{\r
719 UINT32 Crc;\r
720\r
721 Hdr->CRC32 = 0;\r
722 gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);\r
723 Hdr->CRC32 = Crc;\r
724}\r
725\r
726\r
727/**\r
ea7cb08c 728 Checks the CRC32 value in the table header.\r
adbcbf8f 729\r
a8d0c20e 730 @param MaxSize Max Size limit\r
731 @param Hdr Table to check\r
adbcbf8f 732\r
a8d0c20e 733 @return TRUE CRC Valid\r
734 @return FALSE CRC Invalid\r
adbcbf8f 735\r
736**/\r
737BOOLEAN\r
738PartitionCheckCrc (\r
739 IN UINTN MaxSize,\r
740 IN OUT EFI_TABLE_HEADER *Hdr\r
741 )\r
742{\r
743 return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr);\r
744}\r
745\r
746\r
747/**\r
ea7cb08c 748 Checks the CRC32 value in the table header.\r
adbcbf8f 749\r
a8d0c20e 750 @param MaxSize Max Size limit\r
751 @param Size The size of the table\r
752 @param Hdr Table to check\r
adbcbf8f 753\r
754 @return TRUE CRC Valid\r
755 @return FALSE CRC Invalid\r
756\r
757**/\r
758BOOLEAN\r
759PartitionCheckCrcAltSize (\r
760 IN UINTN MaxSize,\r
761 IN UINTN Size,\r
762 IN OUT EFI_TABLE_HEADER *Hdr\r
763 )\r
764{\r
765 UINT32 Crc;\r
766 UINT32 OrgCrc;\r
767 EFI_STATUS Status;\r
768\r
769 Crc = 0;\r
770\r
771 if (Size == 0) {\r
772 //\r
773 // If header size is 0 CRC will pass so return FALSE here\r
774 //\r
775 return FALSE;\r
776 }\r
777\r
ea7cb08c 778 if ((MaxSize != 0) && (Size > MaxSize)) {\r
adbcbf8f 779 DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n"));\r
780 return FALSE;\r
781 }\r
782 //\r
783 // clear old crc from header\r
784 //\r
785 OrgCrc = Hdr->CRC32;\r
786 Hdr->CRC32 = 0;\r
787\r
788 Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc);\r
789 if (EFI_ERROR (Status)) {\r
790 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n"));\r
791 return FALSE;\r
792 }\r
793 //\r
794 // set results\r
795 //\r
796 Hdr->CRC32 = Crc;\r
797\r
798 //\r
799 // return status\r
800 //\r
801 DEBUG_CODE_BEGIN ();\r
802 if (OrgCrc != Crc) {\r
803 DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n"));\r
804 }\r
805 DEBUG_CODE_END ();\r
806\r
807 return (BOOLEAN) (OrgCrc == Crc);\r
808}\r