--- /dev/null
+/** @file\r
+ Routines supporting partition discovery and\r
+ logical device reading\r
+\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
+distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\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[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
+\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