EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

FatPkg/FatPei/Part.c

Go to the documentation of this file.
00001 
00013 #include <IndustryStandard/Mbr.h>
00014 #include <IndustryStandard/ElTorito.h>
00015 #include "FatLitePeim.h"
00016 
00029 BOOLEAN
00030 FatFindEltoritoPartitions (
00031   IN  PEI_FAT_PRIVATE_DATA *PrivateData,
00032   IN  UINTN                ParentBlockDevNo
00033   );
00034 
00047 BOOLEAN
00048 FatFindMbrPartitions (
00049   IN  PEI_FAT_PRIVATE_DATA *PrivateData,
00050   IN  UINTN                ParentBlockDevNo
00051   );
00052 
00053 
00060 VOID
00061 FatFindPartitions (
00062   IN  PEI_FAT_PRIVATE_DATA  *PrivateData
00063   )
00064 {
00065   BOOLEAN Found;
00066   UINTN   Index;
00067 
00068   do {
00069     Found = FALSE;
00070 
00071     for (Index = 0; Index < PrivateData->BlockDeviceCount; Index++) {
00072       if (!PrivateData->BlockDevice[Index].PartitionChecked) {
00073         Found = FatFindMbrPartitions (PrivateData, Index);
00074         if (!Found) {
00075           Found = FatFindEltoritoPartitions (PrivateData, Index);
00076         }
00077       }
00078     }
00079   } while (Found && PrivateData->BlockDeviceCount <= PEI_FAT_MAX_BLOCK_DEVICE);
00080 }
00081 
00082 
00095 BOOLEAN
00096 FatFindEltoritoPartitions (
00097   IN  PEI_FAT_PRIVATE_DATA *PrivateData,
00098   IN  UINTN                ParentBlockDevNo
00099   )
00100 {
00101   EFI_STATUS              Status;
00102   BOOLEAN                 Found;
00103   PEI_FAT_BLOCK_DEVICE    *BlockDev;
00104   PEI_FAT_BLOCK_DEVICE    *ParentBlockDev;
00105   UINT32                  VolDescriptorLba;
00106   UINT32                  Lba;
00107   CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
00108   ELTORITO_CATALOG        *Catalog;
00109   UINTN                   Check;
00110   UINTN                   Index;
00111   UINTN                   MaxIndex;
00112   UINT16                  *CheckBuffer;
00113   UINT32                  SubBlockSize;
00114   UINT32                  SectorCount;
00115   UINT32                  VolSpaceSize;
00116 
00117   if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
00118     return FALSE;
00119   }
00120 
00121   Found           = FALSE;
00122   ParentBlockDev  = &(PrivateData->BlockDevice[ParentBlockDevNo]);
00123   VolSpaceSize    = 0;
00124 
00125   //
00126   // CD_ROM has the fixed block size as 2048 bytes
00127   //
00128   if (ParentBlockDev->BlockSize != 2048) {
00129     return FALSE;
00130   }
00131 
00132   VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;
00133   Catalog       = (ELTORITO_CATALOG *) VolDescriptor;
00134 
00135   //
00136   // the ISO-9660 volume descriptor starts at 32k on the media
00137   // and CD_ROM has the fixed block size as 2048 bytes, so...
00138   //
00139   VolDescriptorLba = 15;
00140   //
00141   // ((16*2048) / Media->BlockSize) - 1;
00142   //
00143   // Loop: handle one volume descriptor per time
00144   //
00145   while (TRUE) {
00146 
00147     VolDescriptorLba += 1;
00148     if (VolDescriptorLba > ParentBlockDev->LastBlock) {
00149       //
00150       // We are pointing past the end of the device so exit
00151       //
00152       break;
00153     }
00154 
00155     Status = FatReadBlock (
00156               PrivateData,
00157               ParentBlockDevNo,
00158               VolDescriptorLba,
00159               ParentBlockDev->BlockSize,
00160               VolDescriptor
00161               );
00162     if (EFI_ERROR (Status)) {
00163       break;
00164     }
00165     //
00166     // Check for valid volume descriptor signature
00167     //
00168     if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||
00169         CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0
00170         ) {
00171       //
00172       // end of Volume descriptor list
00173       //
00174       break;
00175     }
00176     //
00177     // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte
00178     //
00179     if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {
00180       VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];
00181     }
00182     //
00183     // Is it an El Torito volume descriptor?
00184     //
00185     if (CompareMem (
00186           VolDescriptor->BootRecordVolume.SystemId,
00187           CDVOL_ELTORITO_ID,
00188           sizeof (CDVOL_ELTORITO_ID) - 1
00189           ) != 0) {
00190       continue;
00191     }
00192     //
00193     // Read in the boot El Torito boot catalog
00194     //
00195     Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
00196     if (Lba > ParentBlockDev->LastBlock) {
00197       continue;
00198     }
00199 
00200     Status = FatReadBlock (
00201               PrivateData,
00202               ParentBlockDevNo,
00203               Lba,
00204               ParentBlockDev->BlockSize,
00205               Catalog
00206               );
00207     if (EFI_ERROR (Status)) {
00208       continue;
00209     }
00210     //
00211     // We don't care too much about the Catalog header's contents, but we do want
00212     // to make sure it looks like a Catalog header
00213     //
00214     if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
00215       continue;
00216     }
00217 
00218     Check       = 0;
00219     CheckBuffer = (UINT16 *) Catalog;
00220     for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
00221       Check += CheckBuffer[Index];
00222     }
00223 
00224     if ((Check & 0xFFFF) != 0) {
00225       continue;
00226     }
00227 
00228     MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);
00229     for (Index = 1; Index < MaxIndex; Index += 1) {
00230       //
00231       // Next entry
00232       //
00233       Catalog += 1;
00234 
00235       //
00236       // Check this entry
00237       //
00238       if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
00239         continue;
00240       }
00241 
00242       SubBlockSize  = 512;
00243       SectorCount   = Catalog->Boot.SectorCount;
00244 
00245       switch (Catalog->Boot.MediaType) {
00246 
00247       case ELTORITO_NO_EMULATION:
00248         SubBlockSize  = ParentBlockDev->BlockSize;
00249         SectorCount   = Catalog->Boot.SectorCount;
00250         break;
00251 
00252       case ELTORITO_HARD_DISK:
00253         break;
00254 
00255       case ELTORITO_12_DISKETTE:
00256         SectorCount = 0x50 * 0x02 * 0x0F;
00257         break;
00258 
00259       case ELTORITO_14_DISKETTE:
00260         SectorCount = 0x50 * 0x02 * 0x12;
00261         break;
00262 
00263       case ELTORITO_28_DISKETTE:
00264         SectorCount = 0x50 * 0x02 * 0x24;
00265         break;
00266 
00267       default:
00268         SectorCount   = 0;
00269         SubBlockSize  = ParentBlockDev->BlockSize;
00270         break;
00271       }
00272 
00273       if (SectorCount < 2) {
00274         SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);
00275       }
00276       //
00277       // Register this partition
00278       //
00279       if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
00280 
00281         Found                       = TRUE;
00282 
00283         BlockDev                    = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
00284 
00285         BlockDev->BlockSize         = SubBlockSize;
00286         BlockDev->LastBlock         = SectorCount - 1;
00287         BlockDev->IoAlign           = ParentBlockDev->IoAlign;
00288         BlockDev->Logical           = TRUE;
00289         BlockDev->PartitionChecked  = FALSE;
00290         BlockDev->StartingPos       = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize);
00291         BlockDev->ParentDevNo       = ParentBlockDevNo;
00292 
00293         PrivateData->BlockDeviceCount++;
00294       }
00295     }
00296   }
00297 
00298   ParentBlockDev->PartitionChecked = TRUE;
00299 
00300   return Found;
00301 
00302 }
00303 
00304 
00315 BOOLEAN
00316 PartitionValidMbr (
00317   IN  MASTER_BOOT_RECORD      *Mbr,
00318   IN  EFI_PEI_LBA             LastLba
00319   )
00320 {
00321   UINT32  StartingLBA;
00322   UINT32  EndingLBA;
00323   UINT32  NewEndingLBA;
00324   INTN    Index1;
00325   INTN    Index2;
00326   BOOLEAN MbrValid;
00327 
00328   if (Mbr->Signature != MBR_SIGNATURE) {
00329     return FALSE;
00330   }
00331   //
00332   // The BPB also has this signature, so it can not be used alone.
00333   //
00334   MbrValid = FALSE;
00335   for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {
00336     if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {
00337       continue;
00338     }
00339 
00340     MbrValid    = TRUE;
00341     StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);
00342     EndingLBA   = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;
00343     if (EndingLBA > LastLba) {
00344       //
00345       // Compatability Errata:
00346       //  Some systems try to hide drive space with thier INT 13h driver
00347       //  This does not hide space from the OS driver. This means the MBR
00348       //  that gets created from DOS is smaller than the MBR created from
00349       //  a real OS (NT & Win98). This leads to BlockIo->LastBlock being
00350       //  wrong on some systems FDISKed by the OS.
00351       //
00352       //  return FALSE Because no block devices on a system are implemented
00353       //  with INT 13h
00354       //
00355       return FALSE;
00356     }
00357 
00358     for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {
00359       if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {
00360         continue;
00361       }
00362 
00363       NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;
00364       if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {
00365         //
00366         // This region overlaps with the Index1'th region
00367         //
00368         return FALSE;
00369       }
00370     }
00371   }
00372   //
00373   // Non of the regions overlapped so MBR is O.K.
00374   //
00375   return MbrValid;
00376 }
00377 
00378 
00391 BOOLEAN
00392 FatFindMbrPartitions (
00393   IN  PEI_FAT_PRIVATE_DATA *PrivateData,
00394   IN  UINTN                ParentBlockDevNo
00395   )
00396 {
00397   EFI_STATUS            Status;
00398   MASTER_BOOT_RECORD    *Mbr;
00399   UINTN                 Index;
00400   BOOLEAN               Found;
00401   PEI_FAT_BLOCK_DEVICE  *ParentBlockDev;
00402   PEI_FAT_BLOCK_DEVICE  *BlockDev;
00403 
00404   if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {
00405     return FALSE;
00406   }
00407 
00408   ParentBlockDev  = &(PrivateData->BlockDevice[ParentBlockDevNo]);
00409 
00410   Found           = FALSE;
00411   Mbr             = (MASTER_BOOT_RECORD *) PrivateData->BlockData;
00412 
00413   Status = FatReadBlock (
00414             PrivateData,
00415             ParentBlockDevNo,
00416             0,
00417             ParentBlockDev->BlockSize,
00418             Mbr
00419             );
00420 
00421   if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {
00422     goto Done;
00423   }
00424   //
00425   // We have a valid mbr - add each partition
00426   //
00427   for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {
00428     if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {
00429       //
00430       // Don't use null MBR entries
00431       //
00432       continue;
00433     }
00434     //
00435     // Register this partition
00436     //
00437     if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {
00438 
00439       Found                       = TRUE;
00440 
00441       BlockDev                    = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);
00442 
00443       BlockDev->BlockSize         = MBR_SIZE;
00444       BlockDev->LastBlock         = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;
00445       BlockDev->IoAlign           = ParentBlockDev->IoAlign;
00446       BlockDev->Logical           = TRUE;
00447       BlockDev->PartitionChecked  = FALSE;
00448       BlockDev->StartingPos = MultU64x32 (
00449                                 UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),
00450                                 ParentBlockDev->BlockSize
00451                                 );
00452       BlockDev->ParentDevNo = ParentBlockDevNo;
00453 
00454       PrivateData->BlockDeviceCount++;
00455     }
00456   }
00457 
00458 Done:
00459 
00460   ParentBlockDev->PartitionChecked = TRUE;
00461   return Found;
00462 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines