EFI_STATUS EFIAPI fsw_efi_DriverBinding_Supported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath) { EFI_STATUS Status; EFI_DISK_IO *DiskIo; // we check for both DiskIO and BlockIO protocols // first, open DiskIO VBoxLogFlowFuncEnter(); VBoxLogFlowFuncMarkDP(RemainingDevicePath); Status = BS->OpenProtocol(ControllerHandle, &PROTO_NAME(DiskIoProtocol), (VOID **) &DiskIo, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(Status)) { VBoxLogFlowFuncLeaveRC(Status); return Status; } // we were just checking, close it again BS->CloseProtocol(ControllerHandle, &PROTO_NAME(DiskIoProtocol), This->DriverBindingHandle, ControllerHandle); // next, check BlockIO without actually opening it Status = BS->OpenProtocol(ControllerHandle, &PROTO_NAME(BlockIoProtocol), NULL, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); VBoxLogFlowFuncLeaveRC(Status); return Status; }
/** Install child handles if the Handle supports MBR format. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path. @retval EFI_SUCCESS A child handle was added. @retval EFI_MEDIA_CHANGED Media change was detected. @retval Others MBR partition was not found. **/ EFI_STATUS PartitionInstallMbrChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; MASTER_BOOT_RECORD *Mbr; UINT32 ExtMbrStartingLba; UINTN Index; HARDDRIVE_DEVICE_PATH HdDev; HARDDRIVE_DEVICE_PATH ParentHdDev; EFI_STATUS Found; UINT32 PartitionNumber; EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode; UINT32 BlockSize; UINT32 MediaId; EFI_LBA LastBlock; Found = EFI_NOT_FOUND; BlockSize = BlockIo->Media->BlockSize; MediaId = BlockIo->Media->MediaId; LastBlock = BlockIo->Media->LastBlock; #ifdef VBOX VBoxLogFlowFuncMarkDP(DevicePath); #endif Mbr = AllocatePool (BlockSize); if (Mbr == NULL) { return Found; } Status = DiskIo->ReadDisk ( DiskIo, MediaId, 0, BlockSize, Mbr ); if (EFI_ERROR (Status)) { Found = Status; goto Done; } if (!PartitionValidMbr (Mbr, LastBlock)) { goto Done; } // // We have a valid mbr - add each partition // // // Get starting and ending LBA of the parent block device. // LastDevicePathNode = NULL; ZeroMem (&ParentHdDev, sizeof (ParentHdDev)); DevicePathNode = DevicePath; while (!IsDevicePathEnd (DevicePathNode)) { LastDevicePathNode = DevicePathNode; DevicePathNode = NextDevicePathNode (DevicePathNode); } if (LastDevicePathNode != NULL) { if (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH && DevicePathSubType (LastDevicePathNode) == MEDIA_HARDDRIVE_DP ) { CopyMem (&ParentHdDev, LastDevicePathNode, sizeof (ParentHdDev)); } else { LastDevicePathNode = NULL; } } PartitionNumber = 1; ZeroMem (&HdDev, sizeof (HdDev)); HdDev.Header.Type = MEDIA_DEVICE_PATH; HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); HdDev.MBRType = MBR_TYPE_PCAT; HdDev.SignatureType = SIGNATURE_TYPE_MBR; if (LastDevicePathNode == NULL) { // // This is a MBR, add each partition // for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA) == 0) { // // Don't use null MBR entries // continue; } if (Mbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION) { // // This is the guard MBR for the GPT. If you ever see a GPT disk with zero partitions you can get here. // We can not produce an MBR BlockIo for this device as the MBR spans the GPT headers. So formating // this BlockIo would corrupt the GPT structures and require a recovery that would corrupt the format // that corrupted the GPT partition. // continue; } HdDev.PartitionNumber = PartitionNumber ++; HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[Index].StartingLBA); HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA); CopyMem (HdDev.Signature, &(Mbr->UniqueMbrSignature[0]), sizeof (Mbr->UniqueMbrSignature)); Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, HdDev.PartitionStart, HdDev.PartitionStart + HdDev.PartitionSize - 1, MBR_SIZE, (BOOLEAN) (Mbr->Partition[Index].OSIndicator == EFI_PARTITION) ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } else { // // It's an extended partition. Follow the extended partition // chain to get all the logical drives // ExtMbrStartingLba = 0; do { Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32 (ExtMbrStartingLba, BlockSize), BlockSize, Mbr ); if (EFI_ERROR (Status)) { Found = Status; goto Done; } if (UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA) == 0) { break; } if ((Mbr->Partition[0].OSIndicator == EXTENDED_DOS_PARTITION) || (Mbr->Partition[0].OSIndicator == EXTENDED_WINDOWS_PARTITION)) { ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA); continue; } HdDev.PartitionNumber = PartitionNumber ++; HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA) + ExtMbrStartingLba + ParentHdDev.PartitionStart; HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA); if ((HdDev.PartitionStart + HdDev.PartitionSize - 1 >= ParentHdDev.PartitionStart + ParentHdDev.PartitionSize) || (HdDev.PartitionStart <= ParentHdDev.PartitionStart)) { break; } // // The signature in EBR(Extended Boot Record) should always be 0. // *((UINT32 *) &HdDev.Signature[0]) = 0; Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, HdDev.PartitionStart - ParentHdDev.PartitionStart, HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1, MBR_SIZE, (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION) ); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } if ((Mbr->Partition[1].OSIndicator != EXTENDED_DOS_PARTITION) && (Mbr->Partition[1].OSIndicator != EXTENDED_WINDOWS_PARTITION) ) { break; } ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[1].StartingLBA); // // Don't allow partition to be self referencing // if (ExtMbrStartingLba == 0) { break; } } while (ExtMbrStartingLba < ParentHdDev.PartitionSize); } Done: FreePool (Mbr); return Found; }
/** Install child handles if the Handle supports GPT partition structure. @param[in] This Calling context. @param[in] Handle Parent Handle. @param[in] DiskIo Parent DiskIo interface. @param[in] BlockIo Parent BlockIo interface. @param[in] BlockIo2 Parent BlockIo2 interface. @param[in] DevicePath Parent Device Path. @retval EFI_SUCCESS Valid GPT disk. @retval EFI_MEDIA_CHANGED Media changed Detected. @retval other Not a valid GPT disk. **/ EFI_STATUS PartitionInstallGptChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; UINT32 BlockSize; EFI_LBA LastBlock; MASTER_BOOT_RECORD *ProtectiveMbr; EFI_PARTITION_TABLE_HEADER *PrimaryHeader; EFI_PARTITION_TABLE_HEADER *BackupHeader; EFI_PARTITION_ENTRY *PartEntry; EFI_PARTITION_ENTRY *Entry; EFI_PARTITION_ENTRY_STATUS *PEntryStatus; UINTN Index; EFI_STATUS GptValidStatus; HARDDRIVE_DEVICE_PATH HdDev; UINT32 MediaId; VBoxLogFlowFuncMarkDP(DevicePath); ProtectiveMbr = NULL; PrimaryHeader = NULL; BackupHeader = NULL; PartEntry = NULL; PEntryStatus = NULL; BlockSize = BlockIo->Media->BlockSize; LastBlock = BlockIo->Media->LastBlock; MediaId = BlockIo->Media->MediaId; DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize)); DEBUG ((EFI_D_INFO, " LastBlock : %lx \n", LastBlock)); GptValidStatus = EFI_NOT_FOUND; // // Allocate a buffer for the Protective MBR // ProtectiveMbr = AllocatePool (BlockSize); if (ProtectiveMbr == NULL) { return EFI_NOT_FOUND; } // // Read the Protective MBR from LBA #0 // Status = DiskIo->ReadDisk ( DiskIo, MediaId, 0, BlockSize, ProtectiveMbr ); if (EFI_ERROR (Status)) { GptValidStatus = Status; goto Done; } // // Verify that the Protective MBR is valid // for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { if (ProtectiveMbr->Partition[Index].BootIndicator == 0x00 && ProtectiveMbr->Partition[Index].OSIndicator == PMBR_GPT_PARTITION && UNPACK_UINT32 (ProtectiveMbr->Partition[Index].StartingLBA) == 1 ) { break; } } if (Index == MAX_MBR_PARTITIONS) { goto Done; } // // Allocate the GPT structures // PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); if (PrimaryHeader == NULL) { goto Done; } BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); if (BackupHeader == NULL) { goto Done; } // // Check primary and backup partition tables // if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n")); if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) { DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n")); goto Done; } else { DEBUG ((EFI_D_INFO, " Valid backup partition table\n")); DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n")); if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) { DEBUG ((EFI_D_INFO, " Restore primary partition table error\n")); } if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); } } } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n")); DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n")); if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table error\n")); } if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); } } DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n")); // // Read the EFI Partition Entries // PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * PrimaryHeader->SizeOfPartitionEntry); if (PartEntry == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); goto Done; } Status = DiskIo->ReadDisk ( DiskIo, MediaId, MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize), PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry), PartEntry ); if (EFI_ERROR (Status)) { GptValidStatus = Status; DEBUG ((EFI_D_ERROR, " Partition Entry ReadDisk error\n")); goto Done; } DEBUG ((EFI_D_INFO, " Partition entries read block success\n")); DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries)); PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS)); if (PEntryStatus == NULL) { DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); goto Done; } // // Check the integrity of partition entries // PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus); // // If we got this far the GPT layout of the disk is valid and we should return true // GptValidStatus = EFI_SUCCESS; // // Create child device handles // for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { Entry = (EFI_PARTITION_ENTRY *) ((UINT8 *) PartEntry + Index * PrimaryHeader->SizeOfPartitionEntry); if (CompareGuid (&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid) || PEntryStatus[Index].OutOfRange || PEntryStatus[Index].Overlap || PEntryStatus[Index].OsSpecific ) { // // Don't use null EFI Partition Entries, Invalid Partition Entries or OS specific // partition Entries // continue; } ZeroMem (&HdDev, sizeof (HdDev)); HdDev.Header.Type = MEDIA_DEVICE_PATH; HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); HdDev.PartitionNumber = (UINT32) Index + 1; HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; HdDev.SignatureType = SIGNATURE_TYPE_GUID; HdDev.PartitionStart = Entry->StartingLBA; HdDev.PartitionSize = Entry->EndingLBA - Entry->StartingLBA + 1; CopyMem (HdDev.Signature, &Entry->UniquePartitionGUID, sizeof (EFI_GUID)); DEBUG ((EFI_D_INFO, " Index : %d\n", (UINT32) Index)); DEBUG ((EFI_D_INFO, " Start LBA : %lx\n", (UINT64) HdDev.PartitionStart)); DEBUG ((EFI_D_INFO, " End LBA : %lx\n", (UINT64) Entry->EndingLBA)); DEBUG ((EFI_D_INFO, " Partition size: %lx\n", (UINT64) HdDev.PartitionSize)); DEBUG ((EFI_D_INFO, " Start : %lx", MultU64x32 (Entry->StartingLBA, BlockSize))); DEBUG ((EFI_D_INFO, " End : %lx\n", MultU64x32 (Entry->EndingLBA, BlockSize))); Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, Entry->StartingLBA, Entry->EndingLBA, BlockSize, CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid) ); } DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n")); Done: if (ProtectiveMbr != NULL) { FreePool (ProtectiveMbr); } if (PrimaryHeader != NULL) { FreePool (PrimaryHeader); } if (BackupHeader != NULL) { FreePool (BackupHeader); } if (PartEntry != NULL) { FreePool (PartEntry); } if (PEntryStatus != NULL) { FreePool (PEntryStatus); } return GptValidStatus; }
/** Install child handles if the Handle supports Apple partition table format. @param[in] This Calling context. @param[in] Handle Parent Handle @param[in] DiskIo Parent DiskIo interface @param[in] BlockIo Parent BlockIo 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 PartitionInstallAppleChildHandles ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Handle, IN EFI_DISK_IO_PROTOCOL *DiskIo, IN EFI_BLOCK_IO_PROTOCOL *BlockIo, IN EFI_BLOCK_IO2_PROTOCOL *BlockIo2, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; UINT32 Lba; EFI_BLOCK_IO_MEDIA *Media; VOID *Block; //UINTN MaxIndex; /** @todo: wrong, as this PT can be on both HDD or CD */ CDROM_DEVICE_PATH CdDev; //EFI_DEVICE_PATH_PROTOCOL Dev; EFI_STATUS Found; UINT32 Partition; UINT32 PartitionEntries; UINT32 VolSpaceSize; UINT32 SubBlockSize; UINT32 BlkPerSec; VBoxLogFlowFuncMarkDP(DevicePath); Found = EFI_NOT_FOUND; Media = BlockIo->Media; VolSpaceSize = 0; Block = AllocatePool ((UINTN) Media->BlockSize); if (Block == NULL) { return EFI_NOT_FOUND; } do { APPLE_PT_HEADER * Header; /* read PT header first */ Lba = 0; Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Lba, Media->BlockSize), Media->BlockSize, Block ); if (EFI_ERROR (Status)) { Found = Status; break; } Header = (APPLE_PT_HEADER *)Block; if (be16_to_cpu(Header->sbSig) != 0x4552) { break; } SubBlockSize = be16_to_cpu(Header->sbBlkSize); BlkPerSec = Media->BlockSize / SubBlockSize; /* Fail if media block size isn't an exact multiple */ if (Media->BlockSize != SubBlockSize * BlkPerSec) { break; } /* Now iterate over PT entries and install child handles */ PartitionEntries = 1; for (Partition = 1; Partition <= PartitionEntries; Partition++) { APPLE_PT_ENTRY * Entry; UINT32 StartLba; UINT32 SizeLbs; Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Partition, SubBlockSize), SubBlockSize, Block ); if (EFI_ERROR (Status)) { Status = EFI_NOT_FOUND; goto done; /* would break, but ... */ } Entry = (APPLE_PT_ENTRY *)Block; if (be16_to_cpu(Entry->signature) != 0x504D) { Print(L"Not a new PT entry: %x", Entry->signature); continue; } /* First partition contains partitions count */ if (Partition == 1) { PartitionEntries = be32_to_cpu(Entry->map_entries); } StartLba = be32_to_cpu(Entry->pblock_start); SizeLbs = be32_to_cpu(Entry->pblocks); if (0 && CompareMem("Apple_HFS", Entry->type, 10) == 0) Print(L"HFS partition (%d of %d) at LBA 0x%x size=%dM\n", Partition, PartitionEntries, StartLba, (UINT32)(MultU64x32(SizeLbs, SubBlockSize) / (1024 * 1024))); ZeroMem (&CdDev, sizeof (CdDev)); CdDev.Header.Type = MEDIA_DEVICE_PATH; CdDev.Header.SubType = MEDIA_CDROM_DP; SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev)); CdDev.BootEntry = 0; /* Convert from partition to media blocks */ CdDev.PartitionStart = StartLba / BlkPerSec; /* start, LBA */ CdDev.PartitionSize = SizeLbs / BlkPerSec; /* size, LBs */ Status = PartitionInstallChildHandle ( This, Handle, DiskIo, BlockIo, BlockIo2, DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &CdDev, CdDev.PartitionStart, CdDev.PartitionStart + CdDev.PartitionSize - 1, SubBlockSize, FALSE); if (!EFI_ERROR (Status)) { Found = EFI_SUCCESS; } } } while (0); done: FreePool (Block); 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] 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_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; #ifdef VBOX VBoxLogFlowFuncMarkDP(DevicePath); #endif 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 // 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 // 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 // Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog); if (Lba > Media->LastBlock) { continue; } Status = DiskIo->ReadDisk ( DiskIo, Media->MediaId, MultU64x32 (Lba, Media->BlockSize), Media->BlockSize, 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; 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; 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, 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; }
/** Test to see if this driver supports ControllerHandle. Any ControllerHandle than contains a BlockIo and DiskIo protocol or a BlockIo2 protocol can be supported. @param[in] This Protocol instance pointer. @param[in] ControllerHandle Handle of device to test. @param[in] RemainingDevicePath Optional parameter use to pick a specific child device to start. @retval EFI_SUCCESS This driver supports this device @retval EFI_ALREADY_STARTED This driver is already running on this device @retval other This driver does not support this device **/ EFI_STATUS EFIAPI PartitionDriverBindingSupported ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath ) { EFI_STATUS Status; EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; EFI_DISK_IO_PROTOCOL *DiskIo; EFI_DEV_PATH *Node; VBoxLogFlowFuncEnter(); // // Check RemainingDevicePath validation // if (RemainingDevicePath != NULL) { // // Check if RemainingDevicePath is the End of Device Path Node, // if yes, go on checking other conditions // VBoxLogFlowFuncMarkDP(RemainingDevicePath); if (!IsDevicePathEnd (RemainingDevicePath)) { // // If RemainingDevicePath isn't the End of Device Path Node, // check its validation // Node = (EFI_DEV_PATH *) RemainingDevicePath; if ( Node->DevPath.Type != MEDIA_DEVICE_PATH || Node->DevPath.SubType != MEDIA_HARDDRIVE_DP || DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH) || Node->DevPath.Type != MESSAGING_DEVICE_PATH || Node->DevPath.SubType != MSG_SATA_DP) { VBoxLogFlowFuncLeaveRC(EFI_UNSUPPORTED); return EFI_UNSUPPORTED; } } } // // Open the IO Abstraction(s) needed to perform the supported test // Status = gBS->OpenProtocol ( ControllerHandle, &gEfiDiskIoProtocolGuid, (VOID **) &DiskIo, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (Status == EFI_ALREADY_STARTED) { VBoxLogFlowFuncLeaveRC(EFI_SUCCESS); return EFI_SUCCESS; } if (EFI_ERROR (Status)) { VBoxLogFlowFuncLeaveRC(Status); return Status; } // // Close the I/O Abstraction(s) used to perform the supported test // gBS->CloseProtocol ( ControllerHandle, &gEfiDiskIoProtocolGuid, This->DriverBindingHandle, ControllerHandle ); // // Open the EFI Device Path protocol needed to perform the supported test // Status = gBS->OpenProtocol ( ControllerHandle, &gEfiDevicePathProtocolGuid, (VOID **) &ParentDevicePath, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); VBoxLogFlowFuncMarkDP(ParentDevicePath); if (Status == EFI_ALREADY_STARTED) { VBoxLogFlowFuncLeaveRC(EFI_SUCCESS); return EFI_SUCCESS; } if (EFI_ERROR (Status)) { VBoxLogFlowFuncLeaveRC(Status); return Status; } // // Close protocol, don't use device path protocol in the Support() function // gBS->CloseProtocol ( ControllerHandle, &gEfiDevicePathProtocolGuid, This->DriverBindingHandle, ControllerHandle ); // // Open the IO Abstraction(s) needed to perform the supported test // Status = gBS->OpenProtocol ( ControllerHandle, &gEfiBlockIoProtocolGuid, NULL, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL ); if (EFI_ERROR (Status)) { VBoxLogFlowFuncLeaveRC(Status); return Status; } VBoxLogFlowFuncLeaveRC(EFI_SUCCESS); return EFI_SUCCESS; }