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