/** Install child handles if the Handle supports El Torito format. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] DiskIo2 Parent DiskIo2 interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path @retval EFI_SUCCESS Child handle(s) was added. @retval EFI_MEDIA_CHANGED Media changed Detected. @retval other no child handle was added. **/ EFI_STATUS PartitionInstallElToritoChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; UINT32 VolDescriptorLba; UINT32 Lba; EFI_BLOCK_IO_MEDIA *Media; CDROM_VOLUME_DESCRIPTOR *VolDescriptor; ELTORITO_CATALOG *Catalog; UINTN Check; UINTN Index; UINTN BootEntry; UINTN MaxIndex; UINT16 *CheckBuffer; CDROM_DEVICE_PATH CdDev; UINT32 SubBlockSize; UINT32 SectorCount; EFI_STATUS Found; UINT32 VolSpaceSize; Found = EFI_NOT_FOUND; Media = BlockIo->Media; VolSpaceSize = 0; // // CD_ROM has the fixed block size as 2048 bytes // if (Media->BlockSize != 2048) { return EFI_NOT_FOUND; } VolDescriptor = AllocatePool ((UINTN) Media->BlockSize); if (VolDescriptor == NULL) { return EFI_NOT_FOUND; } Catalog = (ELTORITO_CATALOG *) VolDescriptor; // // the ISO-9660 volume descriptor starts at 32k on the media // and CD_ROM has the fixed block size as 2048 bytes, so... // // // ((16*2048) / Media->BlockSize) - 1; // VolDescriptorLba = 15; // // Loop: handle one volume descriptor per time // while (TRUE) { VolDescriptorLba += 1; if (VolDescriptorLba > Media->LastBlock) { // // We are pointing past the end of the device so exit // // DBG("ELT: end of media\n") break; } Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (VolDescriptorLba, Media->BlockSize), Media->BlockSize, VolDescriptor ); if (EFI_ERROR (Status)) { Found = Status; break; } // // Check for valid volume descriptor signature // if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END || CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0 ) { // // end of Volume descriptor list // // DBG("ELT: end of Volume descriptor list\n"); break; } // // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte, // the 32-bit numerical values is stored in Both-byte orders // if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) { VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0]; DBG("ELT: VolSpaceSize =%d\n", VolSpaceSize); } // // Is it an El Torito volume descriptor? // if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) { continue; } // // Read in the boot El Torito boot catalog // Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog); DBG("ELT: this is ELT at lba=%d\n", Lba); if (Lba > Media->LastBlock) { continue; } Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Lba, Media->BlockSize), Media->BlockSize, Catalog ); if (EFI_ERROR (Status)) { DBG ("EltCheckDevice: error reading catalog %r\n", Status); continue; } // // We don't care too much about the Catalog header's contents, but we do want // to make sure it looks like a Catalog header // if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) { DBG ("EltCheckBootCatalog: El Torito boot catalog header IDs=%x not correct\n", Catalog->Catalog.Indicator); continue; } Check = 0; CheckBuffer = (UINT16 *) Catalog; for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) { Check += CheckBuffer[Index]; } if ((Check & 0xFFFF) != 0) { DBG ( "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n"); continue; } MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG); for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) { // // Next entry // Catalog += 1; // // Check this entry // if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) { continue; } SubBlockSize = 512; SectorCount = Catalog->Boot.SectorCount; DBG("ELT: SectorCount =%d\n", SectorCount); switch (Catalog->Boot.MediaType) { case ELTORITO_NO_EMULATION: SubBlockSize = Media->BlockSize; DBG("ELT: SubBlockSize =%d\n", SubBlockSize); break; case ELTORITO_HARD_DISK: break; case ELTORITO_12_DISKETTE: SectorCount = 0x50 * 0x02 * 0x0F; break; case ELTORITO_14_DISKETTE: SectorCount = 0x50 * 0x02 * 0x12; break; case ELTORITO_28_DISKETTE: SectorCount = 0x50 * 0x02 * 0x24; break; default: DBG("EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType); SectorCount = 0; SubBlockSize = Media->BlockSize; break; } // // Create child device handle // CdDev.Header.Type = MEDIA_DEVICE_PATH; CdDev.Header.SubType = MEDIA_CDROM_DP; SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev)); if (Index == 1) { // // This is the initial/default entry // BootEntry = 0; SectorCount = 0; //Slice } CdDev.BootEntry = (UINT32) BootEntry; BootEntry++; CdDev.PartitionStart = Catalog->Boot.Lba; DBG("ELT: Partition start %d\n", CdDev.PartitionStart); if (SectorCount < 2) { // // When the SectorCount < 2, set the Partition as the whole CD. // CdDev.PartitionStart = 0; //Slice if (VolSpaceSize > (Media->LastBlock + 1)) { CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1); } else { CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba); } DBG("ELT: WholeCD PartitionSize=%d\n", CdDev.PartitionSize); } else { CdDev.PartitionSize = DivU64x32 ( MultU64x32 ( SectorCount, SubBlockSize ) + Media->BlockSize - 1, Media->BlockSize ); DBG("ELT: CD Partition%d Size=%d\n", Index, CdDev.PartitionSize); } Status = PartitionInstallChildHandle ( This, Handle, DiskIo, DiskIo2, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &CdDev, Catalog->Boot.Lba, Catalog->Boot.Lba + CdDev.PartitionSize - 1, SubBlockSize, FALSE ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } FreePool (VolDescriptor); return Found; }
/** This function finds Eltorito partitions. Main algorithm is ported from DXE partition driver. @param PrivateData The global memory map @param ParentBlockDevNo The parent block device @retval TRUE New partitions are detected and logical block devices are added to block device array @retval FALSE No New partitions are added; **/ BOOLEAN FatFindEltoritoPartitions ( IN PEI_FAT_PRIVATE_DATA *PrivateData, IN UINTN ParentBlockDevNo ) { EFI_STATUS Status; BOOLEAN Found; PEI_FAT_BLOCK_DEVICE *BlockDev; PEI_FAT_BLOCK_DEVICE *ParentBlockDev; UINT32 VolDescriptorLba; UINT32 Lba; CDROM_VOLUME_DESCRIPTOR *VolDescriptor; ELTORITO_CATALOG *Catalog; UINTN Check; UINTN Index; UINTN MaxIndex; UINT16 *CheckBuffer; UINT32 SubBlockSize; UINT32 SectorCount; UINT32 VolSpaceSize; if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) { return FALSE; } Found = FALSE; ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]); VolSpaceSize = 0; // // CD_ROM has the fixed block size as 2048 bytes // if (ParentBlockDev->BlockSize != 2048) { return FALSE; } VolDescriptor = (CDROM_VOLUME_DESCRIPTOR *) PrivateData->BlockData; Catalog = (ELTORITO_CATALOG *) VolDescriptor; // // the ISO-9660 volume descriptor starts at 32k on the media // and CD_ROM has the fixed block size as 2048 bytes, so... // VolDescriptorLba = 15; // // ((16*2048) / Media->BlockSize) - 1; // // Loop: handle one volume descriptor per time // while (TRUE) { VolDescriptorLba += 1; if (VolDescriptorLba > ParentBlockDev->LastBlock) { // // We are pointing past the end of the device so exit // break; } Status = FatReadBlock ( PrivateData, ParentBlockDevNo, VolDescriptorLba, ParentBlockDev->BlockSize, VolDescriptor ); if (EFI_ERROR (Status)) { break; } // // Check for valid volume descriptor signature // if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END || CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0 ) { // // end of Volume descriptor list // break; } // // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte // if (VolDescriptor->Unknown.Type == CDVOL_TYPE_CODED) { VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[1]; } // // Is it an El Torito volume descriptor? // if (CompareMem ( VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1 ) != 0) { continue; } // // Read in the boot El Torito boot catalog // Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog); if (Lba > ParentBlockDev->LastBlock) { continue; } Status = FatReadBlock ( PrivateData, ParentBlockDevNo, Lba, ParentBlockDev->BlockSize, Catalog ); if (EFI_ERROR (Status)) { continue; } // // We don't care too much about the Catalog header's contents, but we do want // to make sure it looks like a Catalog header // if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) { continue; } Check = 0; CheckBuffer = (UINT16 *) Catalog; for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) { Check += CheckBuffer[Index]; } if ((Check & 0xFFFF) != 0) { continue; } MaxIndex = ParentBlockDev->BlockSize / sizeof (ELTORITO_CATALOG); for (Index = 1; Index < MaxIndex; Index += 1) { // // Next entry // Catalog += 1; // // Check this entry // if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) { continue; } SubBlockSize = 512; SectorCount = Catalog->Boot.SectorCount; switch (Catalog->Boot.MediaType) { case ELTORITO_NO_EMULATION: SubBlockSize = ParentBlockDev->BlockSize; SectorCount = Catalog->Boot.SectorCount; break; case ELTORITO_HARD_DISK: break; case ELTORITO_12_DISKETTE: SectorCount = 0x50 * 0x02 * 0x0F; break; case ELTORITO_14_DISKETTE: SectorCount = 0x50 * 0x02 * 0x12; break; case ELTORITO_28_DISKETTE: SectorCount = 0x50 * 0x02 * 0x24; break; default: SectorCount = 0; SubBlockSize = ParentBlockDev->BlockSize; break; } if (SectorCount < 2) { SectorCount = (VolSpaceSize > ParentBlockDev->LastBlock + 1) ? (UINT32) (ParentBlockDev->LastBlock - Catalog->Boot.Lba + 1) : (UINT32) (VolSpaceSize - Catalog->Boot.Lba); } // // Register this partition // if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) { Found = TRUE; BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]); BlockDev->BlockSize = SubBlockSize; BlockDev->LastBlock = SectorCount - 1; BlockDev->IoAlign = ParentBlockDev->IoAlign; BlockDev->Logical = TRUE; BlockDev->PartitionChecked = FALSE; BlockDev->StartingPos = MultU64x32 (Catalog->Boot.Lba, ParentBlockDev->BlockSize); BlockDev->ParentDevNo = ParentBlockDevNo; PrivateData->BlockDeviceCount++; } } } ParentBlockDev->PartitionChecked = TRUE; return Found; }
/** Test to see if the Mbr buffer is a valid MBR @param Mbr Parent Handle @param LastLba Last Lba address on the device. @retval TRUE Mbr is a Valid MBR @retval FALSE Mbr is not a Valid MBR **/ BOOLEAN PartitionValidMbr ( IN MASTER_BOOT_RECORD *Mbr, IN EFI_PEI_LBA LastLba ) { UINT32 StartingLBA; UINT32 EndingLBA; UINT32 NewEndingLBA; INTN Index1; INTN Index2; BOOLEAN MbrValid; if (Mbr->Signature != MBR_SIGNATURE) { return FALSE; } // // The BPB also has this signature, so it can not be used alone. // MbrValid = FALSE; for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) { if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) { continue; } MbrValid = TRUE; StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA); EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1; if (EndingLBA > LastLba) { // // Compatability Errata: // Some systems try to hide drive space with thier INT 13h driver // This does not hide space from the OS driver. This means the MBR // that gets created from DOS is smaller than the MBR created from // a real OS (NT & Win98). This leads to BlockIo->LastBlock being // wrong on some systems FDISKed by the OS. // // return FALSE Because no block devices on a system are implemented // with INT 13h // return FALSE; } for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) { if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index2].SizeInLBA) == 0) { continue; } NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1; if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) { // // This region overlaps with the Index1'th region // return FALSE; } } } // // Non of the regions overlapped so MBR is O.K. // return MbrValid; }
/** This function finds Mbr partitions. Main algorithm is ported from DXE partition driver. @param PrivateData The global memory map @param ParentBlockDevNo The parent block device @retval TRUE New partitions are detected and logical block devices are added to block device array @retval FALSE No New partitions are added; **/ BOOLEAN FatFindMbrPartitions ( IN PEI_FAT_PRIVATE_DATA *PrivateData, IN UINTN ParentBlockDevNo ) { EFI_STATUS Status; MASTER_BOOT_RECORD *Mbr; UINTN Index; BOOLEAN Found; PEI_FAT_BLOCK_DEVICE *ParentBlockDev; PEI_FAT_BLOCK_DEVICE *BlockDev; if (ParentBlockDevNo > PEI_FAT_MAX_BLOCK_DEVICE - 1) { return FALSE; } ParentBlockDev = &(PrivateData->BlockDevice[ParentBlockDevNo]); Found = FALSE; Mbr = (MASTER_BOOT_RECORD *) PrivateData->BlockData; Status = FatReadBlock ( PrivateData, ParentBlockDevNo, 0, ParentBlockDev->BlockSize, Mbr ); if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, ParentBlockDev->LastBlock)) { goto Done; } // // We have a valid mbr - add each partition // for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) == 0) { // // Don't use null MBR entries // continue; } // // Register this partition // if (PrivateData->BlockDeviceCount < PEI_FAT_MAX_BLOCK_DEVICE) { Found = TRUE; BlockDev = &(PrivateData->BlockDevice[PrivateData->BlockDeviceCount]); BlockDev->BlockSize = MBR_SIZE; BlockDev->LastBlock = UNPACK_INT32 (Mbr->Partition[Index].SizeInLBA) - 1; BlockDev->IoAlign = ParentBlockDev->IoAlign; BlockDev->Logical = TRUE; BlockDev->PartitionChecked = FALSE; BlockDev->StartingPos = MultU64x32 ( UNPACK_INT32 (Mbr->Partition[Index].StartingLBA), ParentBlockDev->BlockSize ); BlockDev->ParentDevNo = ParentBlockDevNo; PrivateData->BlockDeviceCount++; } } Done: ParentBlockDev->PartitionChecked = TRUE; return Found; }
/** Install child handles if the Handle supports El Torito format. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] DiskIo2 Parent DiskIo2 interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path @retval EFI_SUCCESS Child handle(s) was added. @retval EFI_MEDIA_CHANGED Media changed Detected. @retval other no child handle was added. **/ EFI_STATUS PartitionInstallElToritoChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_DISK_IO2_PROTOCOL *DiskIo2, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; UINT64 VolDescriptorOffset; UINT32 Lba2KB; EFI_BLOCK_IO_MEDIA *Media; CDROM_VOLUME_DESCRIPTOR *VolDescriptor; ELTORITO_CATALOG *Catalog; UINTN Check; UINTN Index; UINTN BootEntry; UINTN MaxIndex; UINT16 *CheckBuffer; CDROM_DEVICE_PATH CdDev; UINT32 SubBlockSize; UINT32 SectorCount; EFI_STATUS Found; UINT32 VolSpaceSize; Found = EFI_NOT_FOUND; Media = BlockIo->Media; VolSpaceSize = 0; // // CD_ROM has the fixed block size as 2048 bytes (SIZE_2KB) // // If the ISO image has been copied onto a different storage media // then the block size might be different (eg: USB). // Ensure 2048 (SIZE_2KB) is a multiple of block size if (((SIZE_2KB % Media->BlockSize) != 0) || (Media->BlockSize > SIZE_2KB)) { return EFI_NOT_FOUND; } VolDescriptor = AllocatePool ((UINTN)SIZE_2KB); if (VolDescriptor == NULL) { return EFI_NOT_FOUND; } Catalog = (ELTORITO_CATALOG *) VolDescriptor; // // Loop: handle one volume descriptor per time // The ISO-9660 volume descriptor starts at 32k on the media // for (VolDescriptorOffset = SIZE_32KB; VolDescriptorOffset <= MultU64x32 (Media->LastBlock, Media->BlockSize); VolDescriptorOffset += SIZE_2KB) { Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, VolDescriptorOffset, SIZE_2KB, VolDescriptor ); if (EFI_ERROR (Status)) { Found = Status; break; } // // Check for valid volume descriptor signature // if (VolDescriptor->Unknown.Type == CDVOL_TYPE_END || CompareMem (VolDescriptor->Unknown.Id, CDVOL_ID, sizeof (VolDescriptor->Unknown.Id)) != 0 ) { // // end of Volume descriptor list // break; } // // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte, // the 32-bit numerical values is stored in Both-byte orders // if (VolDescriptor->PrimaryVolume.Type == CDVOL_TYPE_CODED) { VolSpaceSize = VolDescriptor->PrimaryVolume.VolSpaceSize[0]; } // // Is it an El Torito volume descriptor? // if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) { continue; } // // Read in the boot El Torito boot catalog // The LBA unit used by El Torito boot catalog is 2KB unit // Lba2KB = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog); // Ensure the LBA (in 2KB unit) fits into our media if (Lba2KB * (SIZE_2KB / Media->BlockSize) > Media->LastBlock) { continue; } Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Lba2KB, SIZE_2KB), SIZE_2KB, Catalog ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status)); continue; } // // We don't care too much about the Catalog header's contents, but we do want // to make sure it looks like a Catalog header // if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) { DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n")); continue; } Check = 0; CheckBuffer = (UINT16 *) Catalog; for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) { Check += CheckBuffer[Index]; } if ((Check & 0xFFFF) != 0) { DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n")); continue; } MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG); for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) { // // Next entry // Catalog += 1; // // Check this entry // if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) { continue; } SubBlockSize = 512; SectorCount = Catalog->Boot.SectorCount * (SIZE_2KB / Media->BlockSize); switch (Catalog->Boot.MediaType) { case ELTORITO_NO_EMULATION: SubBlockSize = Media->BlockSize; break; case ELTORITO_HARD_DISK: break; case ELTORITO_12_DISKETTE: SectorCount = 0x50 * 0x02 * 0x0F; break; case ELTORITO_14_DISKETTE: SectorCount = 0x50 * 0x02 * 0x12; break; case ELTORITO_28_DISKETTE: SectorCount = 0x50 * 0x02 * 0x24; break; default: DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType)); SectorCount = 0; SubBlockSize = Media->BlockSize; break; } // // Create child device handle // CdDev.Header.Type = MEDIA_DEVICE_PATH; CdDev.Header.SubType = MEDIA_CDROM_DP; SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev)); if (Index == 1) { // // This is the initial/default entry // BootEntry = 0; } CdDev.BootEntry = (UINT32) BootEntry; BootEntry++; CdDev.PartitionStart = Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize); if (SectorCount < 2) { // // When the SectorCount < 2, set the Partition as the whole CD. // if (VolSpaceSize > (Media->LastBlock + 1)) { CdDev.PartitionSize = (UINT32)(Media->LastBlock - Catalog->Boot.Lba + 1); } else { CdDev.PartitionSize = (UINT32)(VolSpaceSize - Catalog->Boot.Lba); } } else { CdDev.PartitionSize = DivU64x32 ( MultU64x32 ( SectorCount, SubBlockSize ) + Media->BlockSize - 1, Media->BlockSize ); } Status = PartitionInstallChildHandle ( This, Handle, DiskIo, DiskIo2, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &CdDev, Catalog->Boot.Lba * (SIZE_2KB / Media->BlockSize), MultU64x32 (Catalog->Boot.Lba + CdDev.PartitionSize - 1, SIZE_2KB / Media->BlockSize), SubBlockSize, FALSE ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } FreePool (VolDescriptor); return Found; }