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