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