]> git.proxmox.com Git - mirror_edk2.git/blame - FatPkg/FatPei/Part.c
FatPkg: Refine casting expression result to bigger size
[mirror_edk2.git] / FatPkg / FatPei / Part.c
CommitLineData
2f4dfa84
JJ
1/** @file\r
2 Routines supporting partition discovery and \r
3 logical device reading\r
4\r
5Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
6\r
7This program and the accompanying materials are licensed and made available\r
8under the terms and conditions of the BSD License which accompanies this\r
9distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include <IndustryStandard/Mbr.h>\r
18#include <IndustryStandard/ElTorito.h>\r
19#include "FatLitePeim.h"\r
20\r
21/**\r
22 This function finds Eltorito partitions. Main algorithm\r
23 is ported from DXE partition driver.\r
24\r
25 @param PrivateData The global memory map \r
26 @param ParentBlockDevNo The parent block device \r
27\r
28 @retval TRUE New partitions are detected and logical block devices \r
29 are added to block device array \r
30 @retval FALSE No New partitions are added;\r
31\r
32**/\r
33BOOLEAN\r
34FatFindEltoritoPartitions (\r
35 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
36 IN UINTN ParentBlockDevNo\r
37 );\r
38\r
39/**\r
40 This function finds Mbr partitions. Main algorithm\r
41 is ported from DXE partition driver.\r
42\r
43 @param PrivateData The global memory map \r
44 @param ParentBlockDevNo The parent block device \r
45\r
46 @retval TRUE New partitions are detected and logical block devices \r
47 are added to block device array \r
48 @retval FALSE No New partitions are added;\r
49\r
50**/\r
51BOOLEAN\r
52FatFindMbrPartitions (\r
53 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
54 IN UINTN ParentBlockDevNo\r
55 );\r
56\r
57\r
58/**\r
59 This function finds partitions (logical devices) in physical block devices.\r
60\r
61 @param PrivateData Global memory map for accessing global variables.\r
62\r
63**/\r
64VOID\r
65FatFindPartitions (\r
66 IN PEI_FAT_PRIVATE_DATA *PrivateData\r
67 )\r
68{\r
69 BOOLEAN Found;\r
70 UINTN Index;\r
71\r
72 do {\r
73 Found = FALSE;\r
74\r
75 for (Index = 0; Index < PrivateData->BlockDeviceCount; Index++) {\r
76 if (!PrivateData->BlockDevice[Index].PartitionChecked) {\r
77 Found = FatFindMbrPartitions (PrivateData, Index);\r
78 if (!Found) {\r
79 Found = FatFindEltoritoPartitions (PrivateData, Index);\r
80 }\r
81 }\r
82 }\r
83 } while (Found && PrivateData->BlockDeviceCount <= PEI_FAT_MAX_BLOCK_DEVICE);\r
84}\r
85\r
86\r
87/**\r
88 This function finds Eltorito partitions. Main algorithm\r
89 is ported from DXE partition driver.\r
90\r
91 @param PrivateData The global memory map \r
92 @param ParentBlockDevNo The parent block device \r
93\r
94 @retval TRUE New partitions are detected and logical block devices \r
95 are added to block device array \r
96 @retval FALSE No New partitions are added;\r
97\r
98**/\r
99BOOLEAN\r
100FatFindEltoritoPartitions (\r
101 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
102 IN UINTN ParentBlockDevNo\r
103 )\r
104{\r
105 EFI_STATUS Status;\r
106 BOOLEAN Found;\r
107 PEI_FAT_BLOCK_DEVICE *BlockDev;\r
108 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
109 UINT32 VolDescriptorLba;\r
110 UINT32 Lba;\r
111 CDROM_VOLUME_DESCRIPTOR *VolDescriptor;\r
112 ELTORITO_CATALOG *Catalog;\r
113 UINTN Check;\r
114 UINTN Index;\r
115 UINTN MaxIndex;\r
116 UINT16 *CheckBuffer;\r
117 UINT32 SubBlockSize;\r
118 UINT32 SectorCount;\r
119 UINT32 VolSpaceSize;\r
120\r
121 if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {\r
122 return FALSE;\r
123 }\r
124\r
125 Found = FALSE;\r
126 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
127 VolSpaceSize = 0;\r
128\r
129 //\r
130 // CD_ROM has the fixed block size as 2048 bytes\r
131 //\r
132 if (ParentBlockDev->BlockSize != 2048) {\r
133 return FALSE;\r
134 }\r
135\r
136 VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;\r
137 Catalog = (ELTORITO_CATALOG *) VolDescriptor;\r
138\r
139 //\r
140 // the ISO-9660 volume descriptor starts at 32k on the media\r
141 // and CD_ROM has the fixed block size as 2048 bytes, so...\r
142 //\r
143 VolDescriptorLba = 15;\r
144 //\r
145 // ((16*2048) / Media->BlockSize) - 1;\r
146 //\r
147 // Loop: handle one volume descriptor per time\r
148 //\r
149 while (TRUE) {\r
150\r
151 VolDescriptorLba += 1;\r
152 if (VolDescriptorLba > ParentBlockDev->LastBlock) {\r
153 //\r
154 // We are pointing past the end of the device so exit\r
155 //\r
156 break;\r
157 }\r
158\r
159 Status = FatReadBlock (\r
160 PrivateData,\r
161 ParentBlockDevNo,\r
162 VolDescriptorLba,\r
163 ParentBlockDev->BlockSize,\r
164 VolDescriptor\r
165 );\r
166 if (EFI_ERROR (Status)) {\r
167 break;\r
168 }\r
169 //\r
170 // Check for valid volume descriptor signature\r
171 //\r
172 if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||\r
173 CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0\r
174 ) {\r
175 //\r
176 // end of Volume descriptor list\r
177 //\r
178 break;\r
179 }\r
180 //\r
181 // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte\r
182 //\r
183 if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {\r
184 VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];\r
185 }\r
186 //\r
187 // Is it an El Torito volume descriptor?\r
188 //\r
189 if (CompareMem (\r
190 VolDescriptor->BootRecordVolume.SystemId,\r
191 CDVOL_ELTORITO_ID,\r
192 sizeof (CDVOL_ELTORITO_ID) - 1\r
193 ) != 0) {\r
194 continue;\r
195 }\r
196 //\r
197 // Read in the boot El Torito boot catalog\r
198 //\r
199 Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);\r
200 if (Lba > ParentBlockDev->LastBlock) {\r
201 continue;\r
202 }\r
203\r
204 Status = FatReadBlock (\r
205 PrivateData,\r
206 ParentBlockDevNo,\r
207 Lba,\r
208 ParentBlockDev->BlockSize,\r
209 Catalog\r
210 );\r
211 if (EFI_ERROR (Status)) {\r
212 continue;\r
213 }\r
214 //\r
215 // We don't care too much about the Catalog header's contents, but we do want\r
216 // to make sure it looks like a Catalog header\r
217 //\r
218 if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {\r
219 continue;\r
220 }\r
221\r
222 Check = 0;\r
223 CheckBuffer = (UINT16 *) Catalog;\r
224 for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {\r
225 Check += CheckBuffer[Index];\r
226 }\r
227\r
228 if ((Check & 0xFFFF) != 0) {\r
229 continue;\r
230 }\r
231\r
232 MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);\r
233 for (Index = 1; Index < MaxIndex; Index += 1) {\r
234 //\r
235 // Next entry\r
236 //\r
237 Catalog += 1;\r
238\r
239 //\r
240 // Check this entry\r
241 //\r
242 if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {\r
243 continue;\r
244 }\r
245\r
246 SubBlockSize = 512;\r
247 SectorCount = Catalog->Boot.SectorCount;\r
248\r
249 switch (Catalog->Boot.MediaType) {\r
250\r
251 case ELTORITO_NO_EMULATION:\r
252 SubBlockSize = ParentBlockDev->BlockSize;\r
253 SectorCount = Catalog->Boot.SectorCount;\r
254 break;\r
255\r
256 case ELTORITO_HARD_DISK:\r
257 break;\r
258\r
259 case ELTORITO_12_DISKETTE:\r
260 SectorCount = 0x50 * 0x02 * 0x0F;\r
261 break;\r
262\r
263 case ELTORITO_14_DISKETTE:\r
264 SectorCount = 0x50 * 0x02 * 0x12;\r
265 break;\r
266\r
267 case ELTORITO_28_DISKETTE:\r
268 SectorCount = 0x50 * 0x02 * 0x24;\r
269 break;\r
270\r
271 default:\r
272 SectorCount = 0;\r
273 SubBlockSize = ParentBlockDev->BlockSize;\r
274 break;\r
275 }\r
276\r
277 if (SectorCount < 2) {\r
278 SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);\r
279 }\r
280 //\r
281 // Register this partition\r
282 //\r
283 if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {\r
284\r
285 Found = TRUE;\r
286\r
287 BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);\r
288\r
289 BlockDev->BlockSize = SubBlockSize;\r
290 BlockDev->LastBlock = SectorCount - 1;\r
291 BlockDev->IoAlign = ParentBlockDev->IoAlign;\r
292 BlockDev->Logical = TRUE;\r
293 BlockDev->PartitionChecked = FALSE;\r
294 BlockDev->StartingPos = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize);\r
295 BlockDev->ParentDevNo = ParentBlockDevNo;\r
296\r
297 PrivateData->BlockDeviceCount++;\r
298 }\r
299 }\r
300 }\r
301\r
302 ParentBlockDev->PartitionChecked = TRUE;\r
303\r
304 return Found;\r
305\r
306}\r
307\r
308\r
309/**\r
310 Test to see if the Mbr buffer is a valid MBR\r
311\r
312 @param Mbr Parent Handle \r
313 @param LastLba Last Lba address on the device. \r
314\r
315 @retval TRUE Mbr is a Valid MBR \r
316 @retval FALSE Mbr is not a Valid MBR\r
317\r
318**/\r
319BOOLEAN\r
320PartitionValidMbr (\r
321 IN MASTER_BOOT_RECORD *Mbr,\r
322 IN EFI_PEI_LBA LastLba\r
323 )\r
324{\r
325 UINT32 StartingLBA;\r
326 UINT32 EndingLBA;\r
327 UINT32 NewEndingLBA;\r
328 INTN Index1;\r
329 INTN Index2;\r
330 BOOLEAN MbrValid;\r
331\r
332 if (Mbr->Signature != MBR_SIGNATURE) {\r
333 return FALSE;\r
334 }\r
335 //\r
336 // The BPB also has this signature, so it can not be used alone.\r
337 //\r
338 MbrValid = FALSE;\r
339 for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {\r
340 if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {\r
341 continue;\r
342 }\r
343\r
344 MbrValid = TRUE;\r
345 StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);\r
346 EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;\r
347 if (EndingLBA > LastLba) {\r
348 //\r
349 // Compatability Errata:\r
350 // Some systems try to hide drive space with thier INT 13h driver\r
351 // This does not hide space from the OS driver. This means the MBR\r
352 // that gets created from DOS is smaller than the MBR created from\r
353 // a real OS (NT & Win98). This leads to BlockIo->LastBlock being\r
354 // wrong on some systems FDISKed by the OS.\r
355 //\r
356 // return FALSE Because no block devices on a system are implemented\r
357 // with INT 13h\r
358 //\r
359 return FALSE;\r
360 }\r
361\r
362 for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {\r
363 if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {\r
364 continue;\r
365 }\r
366\r
367 NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;\r
368 if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {\r
369 //\r
370 // This region overlaps with the Index1'th region\r
371 //\r
372 return FALSE;\r
373 }\r
374 }\r
375 }\r
376 //\r
377 // Non of the regions overlapped so MBR is O.K.\r
378 //\r
379 return MbrValid;\r
380}\r
381\r
382\r
383/**\r
384 This function finds Mbr partitions. Main algorithm\r
385 is ported from DXE partition driver.\r
386\r
387 @param PrivateData The global memory map \r
388 @param ParentBlockDevNo The parent block device \r
389\r
390 @retval TRUE New partitions are detected and logical block devices \r
391 are added to block device array \r
392 @retval FALSE No New partitions are added;\r
393\r
394**/\r
395BOOLEAN\r
396FatFindMbrPartitions (\r
397 IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
398 IN UINTN ParentBlockDevNo\r
399 )\r
400{\r
401 EFI_STATUS Status;\r
402 MASTER_BOOT_RECORD *Mbr;\r
403 UINTN Index;\r
404 BOOLEAN Found;\r
405 PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
406 PEI_FAT_BLOCK_DEVICE *BlockDev;\r
407\r
408 if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {\r
409 return FALSE;\r
410 }\r
411\r
412 ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
413\r
414 Found = FALSE;\r
415 Mbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData;\r
416\r
417 Status = FatReadBlock (\r
418 PrivateData,\r
419 ParentBlockDevNo,\r
420 0,\r
421 ParentBlockDev->BlockSize,\r
422 Mbr\r
423 );\r
424\r
425 if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {\r
426 goto Done;\r
427 }\r
428 //\r
429 // We have a valid mbr - add each partition\r
430 //\r
431 for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {\r
432 if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {\r
433 //\r
434 // Don't use null MBR entries\r
435 //\r
436 continue;\r
437 }\r
438 //\r
439 // Register this partition\r
440 //\r
441 if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {\r
442\r
443 Found = TRUE;\r
444\r
445 BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);\r
446\r
447 BlockDev->BlockSize = MBR_SIZE;\r
448 BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;\r
449 BlockDev->IoAlign = ParentBlockDev->IoAlign;\r
450 BlockDev->Logical = TRUE;\r
451 BlockDev->PartitionChecked = FALSE;\r
452 BlockDev->StartingPos = MultU64x32 (\r
453 UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),\r
454 ParentBlockDev->BlockSize\r
455 );\r
456 BlockDev->ParentDevNo = ParentBlockDevNo;\r
457\r
458 PrivateData->BlockDeviceCount++;\r
459 }\r
460 }\r
461\r
462Done:\r
463\r
464 ParentBlockDev->PartitionChecked = TRUE;\r
465 return Found;\r
466}\r