]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/FatPei/Gpt.c
FatPkg: Apply uncrustify changes
[mirror_edk2.git] / FatPkg / FatPei / Gpt.c
CommitLineData
0d18f5db
CC
1/** @file\r
2 Routines supporting partition discovery and\r
3 logical device reading\r
4\r
5Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>\r
6\r
eb6cb4ce 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
0d18f5db
CC
8\r
9**/\r
10\r
11#include <IndustryStandard/Mbr.h>\r
12#include <Uefi/UefiGpt.h>\r
13#include <Library/BaseLib.h>\r
14#include "FatLitePeim.h"\r
15\r
16//\r
17// Assumption: 'a' and 'blocksize' are all UINT32 or UINT64.\r
18// If 'a' and 'blocksize' are not the same type, should use DivU64xU32 to calculate.\r
19//\r
20#define EFI_SIZE_TO_BLOCKS(a, blocksize) (((a) / (blocksize)) + (((a) % (blocksize)) ? 1 : 0))\r
21\r
22//\r
23// GPT Partition Entry Status\r
24//\r
25typedef struct {\r
bcdcc416
MK
26 BOOLEAN OutOfRange;\r
27 BOOLEAN Overlap;\r
28 BOOLEAN OsSpecific;\r
0d18f5db
CC
29} EFI_PARTITION_ENTRY_STATUS;\r
30\r
31/**\r
32 Check if the CRC field in the Partition table header is valid.\r
33\r
34 @param[in] PartHeader Partition table header structure\r
35\r
36 @retval TRUE the CRC is valid\r
37 @retval FALSE the CRC is invalid\r
38\r
39**/\r
40BOOLEAN\r
41PartitionCheckGptHeaderCRC (\r
42 IN EFI_PARTITION_TABLE_HEADER *PartHeader\r
43 )\r
44{\r
bcdcc416
MK
45 UINT32 GptHdrCrc;\r
46 UINT32 Crc;\r
0d18f5db
CC
47\r
48 GptHdrCrc = PartHeader->Header.CRC32;\r
49\r
50 //\r
44c9618a 51 // Set CRC field to zero when doing calculation\r
0d18f5db
CC
52 //\r
53 PartHeader->Header.CRC32 = 0;\r
54\r
55 Crc = CalculateCrc32 (PartHeader, PartHeader->Header.HeaderSize);\r
56\r
57 //\r
58 // Restore Header CRC\r
59 //\r
60 PartHeader->Header.CRC32 = GptHdrCrc;\r
61\r
62 return (GptHdrCrc == Crc);\r
63}\r
64\r
0d18f5db
CC
65/**\r
66 Check if the CRC field in the Partition table header is valid\r
67 for Partition entry array.\r
68\r
69 @param[in] PartHeader Partition table header structure\r
70 @param[in] PartEntry The partition entry array\r
71\r
72 @retval TRUE the CRC is valid\r
73 @retval FALSE the CRC is invalid\r
74\r
75**/\r
76BOOLEAN\r
77PartitionCheckGptEntryArrayCRC (\r
bcdcc416
MK
78 IN EFI_PARTITION_TABLE_HEADER *PartHeader,\r
79 IN EFI_PARTITION_ENTRY *PartEntry\r
0d18f5db
CC
80 )\r
81{\r
bcdcc416
MK
82 UINT32 Crc;\r
83 UINTN Size;\r
0d18f5db 84\r
bcdcc416 85 Size = (UINTN)MultU64x32 (PartHeader->NumberOfPartitionEntries, PartHeader->SizeOfPartitionEntry);\r
0d18f5db
CC
86 Crc = CalculateCrc32 (PartEntry, Size);\r
87\r
bcdcc416 88 return (BOOLEAN)(PartHeader->PartitionEntryArrayCRC32 == Crc);\r
0d18f5db
CC
89}\r
90\r
91/**\r
92 The function is used for valid GPT table. Both for Primary and Backup GPT header.\r
93\r
94 @param[in] PrivateData The global memory map\r
95 @param[in] ParentBlockDevNo The parent block device\r
96 @param[in] IsPrimaryHeader Indicate to which header will be checked.\r
97 @param[in] PartHdr Stores the partition table that is read\r
98\r
99 @retval TRUE The partition table is valid\r
100 @retval FALSE The partition table is not valid\r
101\r
102**/\r
103BOOLEAN\r
104PartitionCheckGptHeader (\r
105 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
106 IN UINTN ParentBlockDevNo,\r
107 IN BOOLEAN IsPrimaryHeader,\r
108 IN EFI_PARTITION_TABLE_HEADER *PartHdr\r
109 )\r
110{\r
bcdcc416
MK
111 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
112 EFI_PEI_LBA Lba;\r
113 EFI_PEI_LBA AlternateLba;\r
114 EFI_PEI_LBA EntryArrayLastLba;\r
0d18f5db 115\r
bcdcc416
MK
116 UINT64 PartitionEntryArraySize;\r
117 UINT64 PartitionEntryBlockNumb;\r
118 UINT32 EntryArraySizeRemainder;\r
0d18f5db
CC
119\r
120 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
121\r
122 if (IsPrimaryHeader) {\r
123 Lba = PRIMARY_PART_HEADER_LBA;\r
124 AlternateLba = ParentBlockDev->LastBlock;\r
125 } else {\r
126 Lba = ParentBlockDev->LastBlock;\r
127 AlternateLba = PRIMARY_PART_HEADER_LBA;\r
128 }\r
129\r
bcdcc416
MK
130 if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) ||\r
131 (PartHdr->Header.Revision != 0x00010000) ||\r
132 (PartHdr->Header.HeaderSize < 92) ||\r
133 (PartHdr->Header.HeaderSize > ParentBlockDev->BlockSize) ||\r
134 (!PartitionCheckGptHeaderCRC (PartHdr)) ||\r
135 (PartHdr->Header.Reserved != 0)\r
136 )\r
137 {\r
0d18f5db
CC
138 DEBUG ((DEBUG_ERROR, "Invalid efi partition table header\n"));\r
139 return FALSE;\r
140 }\r
141\r
142 //\r
143 // | Block0 | Block1 |Block2 ~ FirstUsableLBA - 1|FirstUsableLBA, ... ,LastUsableLBA|LastUsableLBA+1 ~ LastBlock-1| LastBlock |\r
144 // |Protective MBR|Primary Header|Entry Array(At Least 16384)| Partition | Entry Array(At Least 16384) |BackUp Header|\r
145 //\r
146 // 1. Protective MBR is fixed at Block 0.\r
147 // 2. Primary Header is fixed at Block 1.\r
148 // 3. Backup Header is fixed at LastBlock.\r
149 // 4. Must be remain 128*128 bytes for primary entry array.\r
150 // 5. Must be remain 128*128 bytes for backup entry array.\r
151 // 6. SizeOfPartitionEntry must be equals to 128 * 2^n.\r
152 //\r
bcdcc416
MK
153 if ((PartHdr->MyLBA != Lba) ||\r
154 (PartHdr->AlternateLBA != AlternateLba) ||\r
155 (PartHdr->FirstUsableLBA < 2 + EFI_SIZE_TO_BLOCKS (EFI_GPT_PART_ENTRY_MIN_SIZE, ParentBlockDev->BlockSize)) ||\r
156 (PartHdr->LastUsableLBA > ParentBlockDev->LastBlock - 1 - EFI_SIZE_TO_BLOCKS (EFI_GPT_PART_ENTRY_MIN_SIZE, ParentBlockDev->BlockSize)) ||\r
157 (PartHdr->FirstUsableLBA > PartHdr->LastUsableLBA) ||\r
158 (PartHdr->PartitionEntryLBA < 2) ||\r
159 (PartHdr->PartitionEntryLBA > ParentBlockDev->LastBlock - 1) ||\r
160 ((PartHdr->PartitionEntryLBA >= PartHdr->FirstUsableLBA) && (PartHdr->PartitionEntryLBA <= PartHdr->LastUsableLBA)) ||\r
161 (PartHdr->SizeOfPartitionEntry%128 != 0) ||\r
162 (PartHdr->SizeOfPartitionEntry != sizeof (EFI_PARTITION_ENTRY))\r
163 )\r
164 {\r
0d18f5db
CC
165 DEBUG ((DEBUG_ERROR, "Invalid efi partition table header\n"));\r
166 return FALSE;\r
167 }\r
168\r
169 //\r
170 // Ensure the NumberOfPartitionEntries * SizeOfPartitionEntry doesn't overflow.\r
171 //\r
172 if (PartHdr->NumberOfPartitionEntries > DivU64x32 (MAX_UINTN, PartHdr->SizeOfPartitionEntry)) {\r
173 DEBUG ((DEBUG_ERROR, "Memory overflow in GPT Entry Array\n"));\r
174 return FALSE;\r
175 }\r
176\r
177 PartitionEntryArraySize = MultU64x32 (PartHdr->NumberOfPartitionEntries, PartHdr->SizeOfPartitionEntry);\r
178 EntryArraySizeRemainder = 0;\r
179 PartitionEntryBlockNumb = DivU64x32Remainder (PartitionEntryArraySize, ParentBlockDev->BlockSize, &EntryArraySizeRemainder);\r
180 if (EntryArraySizeRemainder != 0) {\r
181 PartitionEntryBlockNumb++;\r
182 }\r
183\r
184 if (IsPrimaryHeader) {\r
185 EntryArrayLastLba = PartHdr->FirstUsableLBA;\r
186 } else {\r
187 EntryArrayLastLba = ParentBlockDev->LastBlock;\r
188 }\r
189\r
190 //\r
191 // Make sure partition entry array not overlaps with partition area or the LastBlock.\r
192 //\r
193 if (PartHdr->PartitionEntryLBA + PartitionEntryBlockNumb > EntryArrayLastLba) {\r
194 DEBUG ((DEBUG_ERROR, "GPT Partition Entry Array Error!\n"));\r
195 DEBUG ((DEBUG_ERROR, "PartitionEntryArraySize = %lu.\n", PartitionEntryArraySize));\r
196 DEBUG ((DEBUG_ERROR, "PartitionEntryLBA = %lu.\n", PartHdr->PartitionEntryLBA));\r
197 DEBUG ((DEBUG_ERROR, "PartitionEntryBlockNumb = %lu.\n", PartitionEntryBlockNumb));\r
198 DEBUG ((DEBUG_ERROR, "EntryArrayLastLba = %lu.\n", EntryArrayLastLba));\r
199 return FALSE;\r
200 }\r
201\r
202 return TRUE;\r
203}\r
204\r
205/**\r
206 This function is used to verify each partition in block device.\r
207\r
208 @param[in] PrivateData The global memory map\r
209 @param[in] ParentBlockDevNo The parent block device\r
210 @param[in] PartHdr Stores the partition table that is read\r
211\r
212 @retval TRUE The partition is valid\r
213 @retval FALSE The partition is not valid\r
214\r
215**/\r
216BOOLEAN\r
217PartitionCheckGptEntryArray (\r
218 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
219 IN UINTN ParentBlockDevNo,\r
220 IN EFI_PARTITION_TABLE_HEADER *PartHdr\r
221 )\r
222{\r
bcdcc416
MK
223 EFI_STATUS Status;\r
224 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
225 PEI_FAT_BLOCK_DEVICE *BlockDevPtr;\r
0d18f5db 226\r
bcdcc416
MK
227 UINT64 PartitionEntryArraySize;\r
228 UINT64 PartitionEntryBlockNumb;\r
229 UINT32 EntryArraySizeRemainder;\r
0d18f5db 230\r
bcdcc416
MK
231 EFI_PARTITION_ENTRY *PartitionEntryBuffer;\r
232 EFI_PARTITION_ENTRY_STATUS *PartitionEntryStatus;\r
0d18f5db 233\r
bcdcc416
MK
234 BOOLEAN Found;\r
235 EFI_LBA StartingLBA;\r
236 EFI_LBA EndingLBA;\r
237 UINTN Index;\r
238 UINTN Index1;\r
239 UINTN Index2;\r
240 EFI_PARTITION_ENTRY *Entry;\r
0d18f5db 241\r
aad4e2ec
CC
242 PartitionEntryBuffer = NULL;\r
243 PartitionEntryStatus = NULL;\r
244\r
bcdcc416
MK
245 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
246 Found = FALSE;\r
0d18f5db
CC
247\r
248 PartitionEntryArraySize = MultU64x32 (PartHdr->NumberOfPartitionEntries, PartHdr->SizeOfPartitionEntry);\r
249 EntryArraySizeRemainder = 0;\r
250 PartitionEntryBlockNumb = DivU64x32Remainder (PartitionEntryArraySize, ParentBlockDev->BlockSize, &EntryArraySizeRemainder);\r
251 if (EntryArraySizeRemainder != 0) {\r
252 PartitionEntryBlockNumb++;\r
253 }\r
bcdcc416 254\r
0d18f5db
CC
255 PartitionEntryArraySize = MultU64x32 (PartitionEntryBlockNumb, ParentBlockDev->BlockSize);\r
256\r
bcdcc416 257 PartitionEntryBuffer = (EFI_PARTITION_ENTRY *)AllocatePages (EFI_SIZE_TO_PAGES ((UINTN)PartitionEntryArraySize));\r
0d18f5db
CC
258 if (PartitionEntryBuffer == NULL) {\r
259 DEBUG ((DEBUG_ERROR, "Allocate memory error!\n"));\r
260 goto EXIT;\r
261 }\r
262\r
bcdcc416 263 PartitionEntryStatus = (EFI_PARTITION_ENTRY_STATUS *)AllocatePages (EFI_SIZE_TO_PAGES (PartHdr->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS)));\r
0d18f5db
CC
264 if (PartitionEntryStatus == NULL) {\r
265 DEBUG ((DEBUG_ERROR, "Allocate memory error!\n"));\r
266 goto EXIT;\r
267 }\r
bcdcc416 268\r
0d18f5db
CC
269 ZeroMem (PartitionEntryStatus, PartHdr->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS));\r
270\r
271 Status = FatReadBlock (\r
272 PrivateData,\r
273 ParentBlockDevNo,\r
274 PartHdr->PartitionEntryLBA,\r
275 (UINTN)PartitionEntryArraySize,\r
276 PartitionEntryBuffer\r
277 );\r
278 if (EFI_ERROR (Status)) {\r
279 DEBUG ((DEBUG_ERROR, "Read partition entry array error!\n"));\r
280 goto EXIT;\r
281 }\r
282\r
283 if (!PartitionCheckGptEntryArrayCRC (PartHdr, PartitionEntryBuffer)) {\r
284 DEBUG ((DEBUG_ERROR, "Partition entries CRC check fail\n"));\r
285 goto EXIT;\r
286 }\r
287\r
288 for (Index1 = 0; Index1 < PartHdr->NumberOfPartitionEntries; Index1++) {\r
bcdcc416 289 Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntryBuffer + Index1 * PartHdr->SizeOfPartitionEntry);\r
0d18f5db
CC
290 if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
291 continue;\r
292 }\r
293\r
294 StartingLBA = Entry->StartingLBA;\r
295 EndingLBA = Entry->EndingLBA;\r
bcdcc416
MK
296 if ((StartingLBA > EndingLBA) ||\r
297 (StartingLBA < PartHdr->FirstUsableLBA) ||\r
298 (StartingLBA > PartHdr->LastUsableLBA) ||\r
299 (EndingLBA < PartHdr->FirstUsableLBA) ||\r
300 (EndingLBA > PartHdr->LastUsableLBA)\r
301 )\r
302 {\r
0d18f5db
CC
303 PartitionEntryStatus[Index1].OutOfRange = TRUE;\r
304 continue;\r
305 }\r
306\r
307 if ((Entry->Attributes & BIT1) != 0) {\r
308 //\r
309 // If Bit 1 is set, this indicate that this is an OS specific GUID partition.\r
310 //\r
311 PartitionEntryStatus[Index1].OsSpecific = TRUE;\r
312 }\r
313\r
314 for (Index2 = Index1 + 1; Index2 < PartHdr->NumberOfPartitionEntries; Index2++) {\r
bcdcc416 315 Entry = (EFI_PARTITION_ENTRY *)((UINT8 *)PartitionEntryBuffer + Index2 * PartHdr->SizeOfPartitionEntry);\r
0d18f5db
CC
316 if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) {\r
317 continue;\r
318 }\r
319\r
bcdcc416 320 if ((Entry->EndingLBA >= StartingLBA) && (Entry->StartingLBA <= EndingLBA)) {\r
0d18f5db
CC
321 //\r
322 // This region overlaps with the Index1'th region\r
323 //\r
bcdcc416
MK
324 PartitionEntryStatus[Index1].Overlap = TRUE;\r
325 PartitionEntryStatus[Index2].Overlap = TRUE;\r
0d18f5db
CC
326 continue;\r
327 }\r
328 }\r
329 }\r
330\r
331 for (Index = 0; Index < PartHdr->NumberOfPartitionEntries; Index++) {\r
bcdcc416 332 if (CompareGuid (&PartitionEntryBuffer[Index].PartitionTypeGUID, &gEfiPartTypeUnusedGuid) ||\r
0d18f5db
CC
333 PartitionEntryStatus[Index].OutOfRange ||\r
334 PartitionEntryStatus[Index].Overlap ||\r
bcdcc416
MK
335 PartitionEntryStatus[Index].OsSpecific)\r
336 {\r
0d18f5db
CC
337 //\r
338 // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific\r
339 // partition Entries\r
340 //\r
341 continue;\r
342 }\r
343\r
344 if (PrivateData->BlockDeviceCount >= PEI_FAT_MAX_BLOCK_DEVICE) {\r
345 break;\r
346 }\r
347\r
bcdcc416
MK
348 Found = TRUE;\r
349 BlockDevPtr = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);\r
0d18f5db
CC
350\r
351 BlockDevPtr->BlockSize = ParentBlockDev->BlockSize;\r
352 BlockDevPtr->LastBlock = PartitionEntryBuffer[Index].EndingLBA;\r
353 BlockDevPtr->IoAlign = ParentBlockDev->IoAlign;\r
354 BlockDevPtr->Logical = TRUE;\r
355 BlockDevPtr->PartitionChecked = FALSE;\r
356 BlockDevPtr->StartingPos = MultU64x32 (\r
357 PartitionEntryBuffer[Index].StartingLBA,\r
358 ParentBlockDev->BlockSize\r
359 );\r
bcdcc416 360 BlockDevPtr->ParentDevNo = ParentBlockDevNo;\r
0d18f5db
CC
361\r
362 PrivateData->BlockDeviceCount++;\r
363\r
bcdcc416 364 DEBUG ((DEBUG_INFO, "Find GPT Partition [0x%lx", PartitionEntryBuffer[Index].StartingLBA, BlockDevPtr->LastBlock));\r
0d18f5db 365 DEBUG ((DEBUG_INFO, ", 0x%lx]\n", BlockDevPtr->LastBlock));\r
bcdcc416 366 DEBUG ((DEBUG_INFO, " BlockSize %x\n", BlockDevPtr->BlockSize));\r
0d18f5db
CC
367 }\r
368\r
369EXIT:\r
370 if (PartitionEntryBuffer != NULL) {\r
371 FreePages (PartitionEntryBuffer, EFI_SIZE_TO_PAGES ((UINTN)PartitionEntryArraySize));\r
372 }\r
373\r
374 if (PartitionEntryStatus != NULL) {\r
375 FreePages (PartitionEntryStatus, EFI_SIZE_TO_PAGES (PartHdr->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS)));\r
376 }\r
377\r
378 return Found;\r
379}\r
380\r
381/**\r
382 The function is used to check GPT structure, include GPT header and GPT entry array.\r
383\r
384 1. Check GPT header.\r
385 2. Check partition entry array.\r
386 3. Check each partitions.\r
387\r
388 @param[in] PrivateData The global memory map\r
389 @param[in] ParentBlockDevNo The parent block device\r
390 @param[in] IsPrimary Indicate primary or backup to be check\r
391\r
392 @retval TRUE Primary or backup GPT structure is valid.\r
393 @retval FALSE Both primary and backup are invalid.\r
394\r
395**/\r
396BOOLEAN\r
397PartitionCheckGptStructure (\r
bcdcc416
MK
398 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
399 IN UINTN ParentBlockDevNo,\r
400 IN BOOLEAN IsPrimary\r
0d18f5db
CC
401 )\r
402{\r
bcdcc416
MK
403 EFI_STATUS Status;\r
404 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
405 EFI_PARTITION_TABLE_HEADER *PartHdr;\r
406 EFI_PEI_LBA GptHeaderLBA;\r
0d18f5db 407\r
bcdcc416
MK
408 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
409 PartHdr = (EFI_PARTITION_TABLE_HEADER *)PrivateData->BlockData;\r
0d18f5db
CC
410\r
411 if (IsPrimary) {\r
412 GptHeaderLBA = PRIMARY_PART_HEADER_LBA;\r
413 } else {\r
414 GptHeaderLBA = ParentBlockDev->LastBlock;\r
415 }\r
416\r
417 Status = FatReadBlock (\r
418 PrivateData,\r
419 ParentBlockDevNo,\r
420 GptHeaderLBA,\r
421 ParentBlockDev->BlockSize,\r
422 PartHdr\r
423 );\r
424 if (EFI_ERROR (Status)) {\r
425 return FALSE;\r
426 }\r
427\r
428 if (!PartitionCheckGptHeader (PrivateData, ParentBlockDevNo, IsPrimary, PartHdr)) {\r
429 return FALSE;\r
430 }\r
431\r
432 if (!PartitionCheckGptEntryArray (PrivateData, ParentBlockDevNo, PartHdr)) {\r
433 return FALSE;\r
434 }\r
435\r
436 return TRUE;\r
437}\r
438\r
439/**\r
440 This function is used to check protective MBR structure before checking GPT.\r
441\r
442 @param[in] PrivateData The global memory map\r
443 @param[in] ParentBlockDevNo The parent block device\r
444\r
445 @retval TRUE Valid protective MBR\r
446 @retval FALSE Invalid MBR\r
447**/\r
448BOOLEAN\r
449PartitionCheckProtectiveMbr (\r
bcdcc416
MK
450 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
451 IN UINTN ParentBlockDevNo\r
0d18f5db
CC
452 )\r
453{\r
bcdcc416
MK
454 EFI_STATUS Status;\r
455 MASTER_BOOT_RECORD *ProtectiveMbr;\r
456 MBR_PARTITION_RECORD *MbrPartition;\r
457 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
458 UINTN Index;\r
0d18f5db 459\r
bcdcc416
MK
460 ProtectiveMbr = (MASTER_BOOT_RECORD *)PrivateData->BlockData;\r
461 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
0d18f5db
CC
462\r
463 //\r
464 // Read Protective MBR\r
465 //\r
466 Status = FatReadBlock (\r
467 PrivateData,\r
468 ParentBlockDevNo,\r
469 0,\r
470 ParentBlockDev->BlockSize,\r
471 ProtectiveMbr\r
472 );\r
473 if (EFI_ERROR (Status)) {\r
474 DEBUG ((DEBUG_ERROR, "GPT Error When Read Protective Mbr From Partition!\n"));\r
475 return FALSE;\r
476 }\r
477\r
478 if (ProtectiveMbr->Signature != MBR_SIGNATURE) {\r
479 DEBUG ((DEBUG_ERROR, "Protective Mbr Signature is invalid!\n"));\r
480 return FALSE;\r
481 }\r
482\r
483 //\r
484 // The partition define in UEFI Spec Table 17.\r
485 // Boot Code, Unique MBR Disk Signature, Unknown.\r
486 // These parts will not be used by UEFI, so we skip to check them.\r
487 //\r
488 for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {\r
489 MbrPartition = (MBR_PARTITION_RECORD *)&ProtectiveMbr->Partition[Index];\r
bcdcc416
MK
490 if ((MbrPartition->BootIndicator == 0x00) &&\r
491 (MbrPartition->StartSector == 0x02) &&\r
492 (MbrPartition->OSIndicator == PMBR_GPT_PARTITION) &&\r
493 (UNPACK_UINT32 (MbrPartition->StartingLBA) == 1)\r
494 )\r
495 {\r
0d18f5db
CC
496 return TRUE;\r
497 }\r
498 }\r
499\r
500 DEBUG ((DEBUG_ERROR, "Protective Mbr, All Partition Entry Are Empty!\n"));\r
501 return FALSE;\r
502}\r
503\r
504/**\r
505 This function is used for finding GPT partition on block device.\r
506 As follow UEFI spec we should check protective MBR first and then\r
507 try to check both primary/backup GPT structures.\r
508\r
509 @param[in] PrivateData The global memory map\r
510 @param[in] ParentBlockDevNo The parent block device\r
511\r
512 @retval TRUE New partitions are detected and logical block devices\r
513 are added to block device array\r
514 @retval FALSE No new partitions are added\r
515\r
516**/\r
517BOOLEAN\r
518FatFindGptPartitions (\r
bcdcc416
MK
519 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
520 IN UINTN ParentBlockDevNo\r
0d18f5db
CC
521 )\r
522{\r
bcdcc416
MK
523 BOOLEAN Found;\r
524 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
0d18f5db
CC
525\r
526 if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {\r
527 return FALSE;\r
528 }\r
529\r
bcdcc416 530 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
0d18f5db
CC
531 if (ParentBlockDev->BlockSize > PEI_FAT_MAX_BLOCK_SIZE) {\r
532 DEBUG ((DEBUG_ERROR, "Device BlockSize %x exceed FAT_MAX_BLOCK_SIZE\n", ParentBlockDev->BlockSize));\r
533 return FALSE;\r
534 }\r
535\r
536 if (!PartitionCheckProtectiveMbr (PrivateData, ParentBlockDevNo)) {\r
537 return FALSE;\r
538 }\r
539\r
540 Found = PartitionCheckGptStructure (PrivateData, ParentBlockDevNo, TRUE);\r
541 if (!Found) {\r
542 DEBUG ((DEBUG_ERROR, "Primary GPT Header Error, Try to Check Backup GPT Header!\n"));\r
543 Found = PartitionCheckGptStructure (PrivateData, ParentBlockDevNo, FALSE);\r
544 }\r
545\r
546 if (Found) {\r
547 ParentBlockDev->PartitionChecked = TRUE;\r
548 }\r
549\r
550 return Found;\r
551}\r