Routines supporting partition discovery and\r
logical device reading\r
\r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials are licensed and made available\r
under the terms and conditions of the BSD License which accompanies this\r
\r
**/\r
\r
-#include <IndustryStandard/Mbr.h>\r
-#include <IndustryStandard/ElTorito.h>\r
#include "FatLitePeim.h"\r
\r
/**\r
This function finds Eltorito partitions. Main algorithm\r
is ported from DXE partition driver.\r
\r
- @param PrivateData The global memory map\r
- @param ParentBlockDevNo The parent block device\r
+ @param[in] PrivateData The global memory map\r
+ @param[in] ParentBlockDevNo The parent block device\r
\r
@retval TRUE New partitions are detected and logical block devices\r
- are added to block device array\r
- @retval FALSE No New partitions are added;\r
+ are added to block device array\r
+ @retval FALSE No new partitions are added\r
\r
**/\r
BOOLEAN\r
This function finds Mbr partitions. Main algorithm\r
is ported from DXE partition driver.\r
\r
- @param PrivateData The global memory map\r
- @param ParentBlockDevNo The parent block device\r
+ @param[in] PrivateData The global memory map\r
+ @param[in] ParentBlockDevNo The parent block device\r
\r
@retval TRUE New partitions are detected and logical block devices\r
- are added to block device array\r
- @retval FALSE No New partitions are added;\r
+ are added to block device array\r
+ @retval FALSE No new partitions are added\r
\r
**/\r
BOOLEAN\r
IN UINTN ParentBlockDevNo\r
);\r
\r
-\r
/**\r
This function finds partitions (logical devices) in physical block devices.\r
\r
} while (Found && PrivateData->BlockDeviceCount <= PEI_FAT_MAX_BLOCK_DEVICE);\r
}\r
\r
-\r
-/**\r
- This function finds Eltorito partitions. Main algorithm\r
- is ported from DXE partition driver.\r
-\r
- @param PrivateData The global memory map\r
- @param ParentBlockDevNo The parent block device\r
-\r
- @retval TRUE New partitions are detected and logical block devices\r
- are added to block device array\r
- @retval FALSE No New partitions are added;\r
-\r
-**/\r
-BOOLEAN\r
-FatFindEltoritoPartitions (\r
- IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
- IN UINTN ParentBlockDevNo\r
- )\r
-{\r
- EFI_STATUS Status;\r
- BOOLEAN Found;\r
- PEI_FAT_BLOCK_DEVICE *BlockDev;\r
- PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
- UINT32 VolDescriptorLba;\r
- UINT32 Lba;\r
- CDROM_VOLUME_DESCRIPTOR *VolDescriptor;\r
- ELTORITO_CATALOG *Catalog;\r
- UINTN Check;\r
- UINTN Index;\r
- UINTN MaxIndex;\r
- UINT16 *CheckBuffer;\r
- UINT32 SubBlockSize;\r
- UINT32 SectorCount;\r
- UINT32 VolSpaceSize;\r
-\r
- if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {\r
- return FALSE;\r
- }\r
-\r
- Found = FALSE;\r
- ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
- VolSpaceSize = 0;\r
-\r
- //\r
- // CD_ROM has the fixed block size as 2048 bytes\r
- //\r
- if (ParentBlockDev->BlockSize != 2048) {\r
- return FALSE;\r
- }\r
-\r
- VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData;\r
- Catalog = (ELTORITO_CATALOG *) VolDescriptor;\r
-\r
- //\r
- // the ISO-9660 volume descriptor starts at 32k on the media\r
- // and CD_ROM has the fixed block size as 2048 bytes, so...\r
- //\r
- VolDescriptorLba = 15;\r
- //\r
- // ((16*2048) / Media->BlockSize) - 1;\r
- //\r
- // Loop: handle one volume descriptor per time\r
- //\r
- while (TRUE) {\r
-\r
- VolDescriptorLba += 1;\r
- if (VolDescriptorLba > ParentBlockDev->LastBlock) {\r
- //\r
- // We are pointing past the end of the device so exit\r
- //\r
- break;\r
- }\r
-\r
- Status = FatReadBlock (\r
- PrivateData,\r
- ParentBlockDevNo,\r
- VolDescriptorLba,\r
- ParentBlockDev->BlockSize,\r
- VolDescriptor\r
- );\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- //\r
- // Check for valid volume descriptor signature\r
- //\r
- if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END ||\r
- CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0\r
- ) {\r
- //\r
- // end of Volume descriptor list\r
- //\r
- break;\r
- }\r
- //\r
- // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte\r
- //\r
- if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) {\r
- VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1];\r
- }\r
- //\r
- // Is it an El Torito volume descriptor?\r
- //\r
- if (CompareMem (\r
- VolDescriptor->BootRecordVolume.SystemId,\r
- CDVOL_ELTORITO_ID,\r
- sizeof (CDVOL_ELTORITO_ID) - 1\r
- ) != 0) {\r
- continue;\r
- }\r
- //\r
- // Read in the boot El Torito boot catalog\r
- //\r
- Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);\r
- if (Lba > ParentBlockDev->LastBlock) {\r
- continue;\r
- }\r
-\r
- Status = FatReadBlock (\r
- PrivateData,\r
- ParentBlockDevNo,\r
- Lba,\r
- ParentBlockDev->BlockSize,\r
- Catalog\r
- );\r
- if (EFI_ERROR (Status)) {\r
- continue;\r
- }\r
- //\r
- // We don't care too much about the Catalog header's contents, but we do want\r
- // to make sure it looks like a Catalog header\r
- //\r
- if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {\r
- continue;\r
- }\r
-\r
- Check = 0;\r
- CheckBuffer = (UINT16 *) Catalog;\r
- for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {\r
- Check += CheckBuffer[Index];\r
- }\r
-\r
- if ((Check & 0xFFFF) != 0) {\r
- continue;\r
- }\r
-\r
- MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG);\r
- for (Index = 1; Index < MaxIndex; Index += 1) {\r
- //\r
- // Next entry\r
- //\r
- Catalog += 1;\r
-\r
- //\r
- // Check this entry\r
- //\r
- if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {\r
- continue;\r
- }\r
-\r
- SubBlockSize = 512;\r
- SectorCount = Catalog->Boot.SectorCount;\r
-\r
- switch (Catalog->Boot.MediaType) {\r
-\r
- case ELTORITO_NO_EMULATION:\r
- SubBlockSize = ParentBlockDev->BlockSize;\r
- SectorCount = Catalog->Boot.SectorCount;\r
- break;\r
-\r
- case ELTORITO_HARD_DISK:\r
- break;\r
-\r
- case ELTORITO_12_DISKETTE:\r
- SectorCount = 0x50 * 0x02 * 0x0F;\r
- break;\r
-\r
- case ELTORITO_14_DISKETTE:\r
- SectorCount = 0x50 * 0x02 * 0x12;\r
- break;\r
-\r
- case ELTORITO_28_DISKETTE:\r
- SectorCount = 0x50 * 0x02 * 0x24;\r
- break;\r
-\r
- default:\r
- SectorCount = 0;\r
- SubBlockSize = ParentBlockDev->BlockSize;\r
- break;\r
- }\r
-\r
- if (SectorCount < 2) {\r
- SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba);\r
- }\r
- //\r
- // Register this partition\r
- //\r
- if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {\r
-\r
- Found = TRUE;\r
-\r
- BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);\r
-\r
- BlockDev->BlockSize = SubBlockSize;\r
- BlockDev->LastBlock = SectorCount - 1;\r
- BlockDev->IoAlign = ParentBlockDev->IoAlign;\r
- BlockDev->Logical = TRUE;\r
- BlockDev->PartitionChecked = FALSE;\r
- BlockDev->StartingPos = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize);\r
- BlockDev->ParentDevNo = ParentBlockDevNo;\r
-\r
- PrivateData->BlockDeviceCount++;\r
- }\r
- }\r
- }\r
-\r
- ParentBlockDev->PartitionChecked = TRUE;\r
-\r
- return Found;\r
-\r
-}\r
-\r
-\r
-/**\r
- Test to see if the Mbr buffer is a valid MBR\r
-\r
- @param Mbr Parent Handle\r
- @param LastLba Last Lba address on the device.\r
-\r
- @retval TRUE Mbr is a Valid MBR\r
- @retval FALSE Mbr is not a Valid MBR\r
-\r
-**/\r
-BOOLEAN\r
-PartitionValidMbr (\r
- IN MASTER_BOOT_RECORD *Mbr,\r
- IN EFI_PEI_LBA LastLba\r
- )\r
-{\r
- UINT32 StartingLBA;\r
- UINT32 EndingLBA;\r
- UINT32 NewEndingLBA;\r
- INTN Index1;\r
- INTN Index2;\r
- BOOLEAN MbrValid;\r
-\r
- if (Mbr->Signature != MBR_SIGNATURE) {\r
- return FALSE;\r
- }\r
- //\r
- // The BPB also has this signature, so it can not be used alone.\r
- //\r
- MbrValid = FALSE;\r
- for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) {\r
- if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) {\r
- continue;\r
- }\r
-\r
- MbrValid = TRUE;\r
- StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA);\r
- EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1;\r
- if (EndingLBA > LastLba) {\r
- //\r
- // Compatability Errata:\r
- // Some systems try to hide drive space with thier INT 13h driver\r
- // This does not hide space from the OS driver. This means the MBR\r
- // that gets created from DOS is smaller than the MBR created from\r
- // a real OS (NT & Win98). This leads to BlockIo->LastBlock being\r
- // wrong on some systems FDISKed by the OS.\r
- //\r
- // return FALSE Because no block devices on a system are implemented\r
- // with INT 13h\r
- //\r
- return FALSE;\r
- }\r
-\r
- for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) {\r
- if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) {\r
- continue;\r
- }\r
-\r
- NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1;\r
- if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) {\r
- //\r
- // This region overlaps with the Index1'th region\r
- //\r
- return FALSE;\r
- }\r
- }\r
- }\r
- //\r
- // Non of the regions overlapped so MBR is O.K.\r
- //\r
- return MbrValid;\r
-}\r
-\r
-\r
-/**\r
- This function finds Mbr partitions. Main algorithm\r
- is ported from DXE partition driver.\r
-\r
- @param PrivateData The global memory map\r
- @param ParentBlockDevNo The parent block device\r
-\r
- @retval TRUE New partitions are detected and logical block devices\r
- are added to block device array\r
- @retval FALSE No New partitions are added;\r
-\r
-**/\r
-BOOLEAN\r
-FatFindMbrPartitions (\r
- IN PEI_FAT_PRIVATE_DATA *PrivateData,\r
- IN UINTN ParentBlockDevNo\r
- )\r
-{\r
- EFI_STATUS Status;\r
- MASTER_BOOT_RECORD *Mbr;\r
- UINTN Index;\r
- BOOLEAN Found;\r
- PEI_FAT_BLOCK_DEVICE *ParentBlockDev;\r
- PEI_FAT_BLOCK_DEVICE *BlockDev;\r
-\r
- if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) {\r
- return FALSE;\r
- }\r
-\r
- ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]);\r
-\r
- Found = FALSE;\r
- Mbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData;\r
-\r
- Status = FatReadBlock (\r
- PrivateData,\r
- ParentBlockDevNo,\r
- 0,\r
- ParentBlockDev->BlockSize,\r
- Mbr\r
- );\r
-\r
- if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) {\r
- goto Done;\r
- }\r
- //\r
- // We have a valid mbr - add each partition\r
- //\r
- for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) {\r
- if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) {\r
- //\r
- // Don't use null MBR entries\r
- //\r
- continue;\r
- }\r
- //\r
- // Register this partition\r
- //\r
- if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) {\r
-\r
- Found = TRUE;\r
-\r
- BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]);\r
-\r
- BlockDev->BlockSize = MBR_SIZE;\r
- BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1;\r
- BlockDev->IoAlign = ParentBlockDev->IoAlign;\r
- BlockDev->Logical = TRUE;\r
- BlockDev->PartitionChecked = FALSE;\r
- BlockDev->StartingPos = MultU64x32 (\r
- UNPACK_INT32 (Mbr->Partition[Index].StartingLBA),\r
- ParentBlockDev->BlockSize\r
- );\r
- BlockDev->ParentDevNo = ParentBlockDevNo;\r
-\r
- PrivateData->BlockDeviceCount++;\r
- }\r
- }\r
-\r
-Done:\r
-\r
- ParentBlockDev->PartitionChecked = TRUE;\r
- return Found;\r
-}\r