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