123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- /** @file
- Collect IDE information from Native EFI Driver
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "LegacyBiosInterface.h"
- BOOLEAN mIdeDataBuiltFlag = FALSE;
- /**
- Collect IDE Inquiry data from the IDE disks
- @param Private Legacy BIOS Instance data
- @param HddInfo Hdd Information
- @param Flag Reconnect IdeController or not
- @retval EFI_SUCCESS It should always work.
- **/
- EFI_STATUS
- LegacyBiosBuildIdeData (
- IN LEGACY_BIOS_INSTANCE *Private,
- IN HDD_INFO **HddInfo,
- IN UINT16 Flag
- )
- {
- EFI_STATUS Status;
- EFI_HANDLE IdeController;
- UINTN HandleCount;
- EFI_HANDLE *HandleBuffer;
- UINTN Index;
- EFI_DISK_INFO_PROTOCOL *DiskInfo;
- UINT32 IdeChannel;
- UINT32 IdeDevice;
- UINT32 Size;
- UINT8 *InquiryData;
- UINT32 InquiryDataSize;
- HDD_INFO *LocalHddInfo;
- UINT32 PciIndex;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;
- EFI_DEVICE_PATH_PROTOCOL *TempDevicePathNode;
- PCI_DEVICE_PATH *PciDevicePath;
- //
- // Only build data once
- // We have a problem with GetBbsInfo in that it can be invoked two
- // places. Once in BDS, when all EFI drivers are connected and once in
- // LegacyBoot after all EFI drivers are disconnected causing this routine
- // to hang. In LegacyBoot this function is also called before EFI drivers
- // are disconnected.
- // Cases covered
- // GetBbsInfo invoked in BDS. Both invocations in LegacyBoot ignored.
- // GetBbsInfo not invoked in BDS. First invocation of this function
- // proceeds normally and second via GetBbsInfo ignored.
- //
- PciDevicePath = NULL;
- LocalHddInfo = *HddInfo;
- Status = Private->LegacyBiosPlatform->GetPlatformHandle (
- Private->LegacyBiosPlatform,
- EfiGetPlatformIdeHandle,
- 0,
- &HandleBuffer,
- &HandleCount,
- (VOID *)&LocalHddInfo
- );
- if (!EFI_ERROR (Status)) {
- IdeController = HandleBuffer[0];
- //
- // Force IDE drive spin up!
- //
- if (Flag != 0) {
- gBS->DisconnectController (
- IdeController,
- NULL,
- NULL
- );
- }
- gBS->ConnectController (IdeController, NULL, NULL, FALSE);
- //
- // Do GetIdeHandle twice since disconnect/reconnect will switch to native mode
- // And GetIdeHandle will switch to Legacy mode, if required.
- //
- Private->LegacyBiosPlatform->GetPlatformHandle (
- Private->LegacyBiosPlatform,
- EfiGetPlatformIdeHandle,
- 0,
- &HandleBuffer,
- &HandleCount,
- (VOID *)&LocalHddInfo
- );
- }
- mIdeDataBuiltFlag = TRUE;
- //
- // Get Identity command from all drives
- //
- gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiDiskInfoProtocolGuid,
- NULL,
- &HandleCount,
- &HandleBuffer
- );
- Private->IdeDriveCount = (UINT8)HandleCount;
- for (Index = 0; Index < HandleCount; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiDiskInfoProtocolGuid,
- (VOID **)&DiskInfo
- );
- ASSERT_EFI_ERROR (Status);
- if (CompareGuid (&DiskInfo->Interface, &gEfiDiskInfoIdeInterfaceGuid)) {
- //
- // Locate which PCI device
- //
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- (VOID *)&DevicePath
- );
- ASSERT_EFI_ERROR (Status);
- DevicePathNode = DevicePath;
- while (!IsDevicePathEnd (DevicePathNode)) {
- TempDevicePathNode = NextDevicePathNode (DevicePathNode);
- if ((DevicePathType (DevicePathNode) == HARDWARE_DEVICE_PATH) &&
- (DevicePathSubType (DevicePathNode) == HW_PCI_DP) &&
- (DevicePathType (TempDevicePathNode) == MESSAGING_DEVICE_PATH) &&
- (DevicePathSubType (TempDevicePathNode) == MSG_ATAPI_DP))
- {
- PciDevicePath = (PCI_DEVICE_PATH *)DevicePathNode;
- break;
- }
- DevicePathNode = NextDevicePathNode (DevicePathNode);
- }
- if (PciDevicePath == NULL) {
- continue;
- }
- //
- // Find start of PCI device in HddInfo. The assumption of the data
- // structure is 2 controllers(channels) per PCI device and each
- // controller can have 2 drives(devices).
- // HddInfo[PciIndex+0].[0] = Channel[0].Device[0] Primary Master
- // HddInfo[PciIndex+0].[1] = Channel[0].Device[1] Primary Slave
- // HddInfo[PciIndex+1].[0] = Channel[1].Device[0] Secondary Master
- // HddInfo[PciIndex+1].[1] = Channel[1].Device[1] Secondary Slave
- // @bug eventually need to pass in max number of entries
- // for end of for loop
- //
- for (PciIndex = 0; PciIndex < 8; PciIndex++) {
- if ((PciDevicePath->Device == LocalHddInfo[PciIndex].Device) &&
- (PciDevicePath->Function == LocalHddInfo[PciIndex].Function)
- )
- {
- break;
- }
- }
- if (PciIndex == 8) {
- continue;
- }
- Status = DiskInfo->WhichIde (DiskInfo, &IdeChannel, &IdeDevice);
- if (!EFI_ERROR (Status)) {
- Size = sizeof (ATAPI_IDENTIFY);
- DiskInfo->Identify (
- DiskInfo,
- &LocalHddInfo[PciIndex + IdeChannel].IdentifyDrive[IdeDevice],
- &Size
- );
- if (IdeChannel == 0) {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_PRIMARY;
- } else if (IdeChannel == 1) {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SECONDARY;
- }
- InquiryData = NULL;
- InquiryDataSize = 0;
- Status = DiskInfo->Inquiry (
- DiskInfo,
- NULL,
- &InquiryDataSize
- );
- if (Status == EFI_BUFFER_TOO_SMALL) {
- InquiryData = (UINT8 *)AllocatePool (
- InquiryDataSize
- );
- if (InquiryData != NULL) {
- Status = DiskInfo->Inquiry (
- DiskInfo,
- InquiryData,
- &InquiryDataSize
- );
- }
- } else {
- Status = EFI_DEVICE_ERROR;
- }
- //
- // If ATAPI device then Inquiry will pass and ATA fail.
- //
- if (!EFI_ERROR (Status)) {
- ASSERT (InquiryData != NULL);
- //
- // If IdeDevice = 0 then set master bit, else slave bit
- //
- if (IdeDevice == 0) {
- if ((InquiryData[0] & 0x1f) == 0x05) {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_CDROM;
- } else if ((InquiryData[0] & 0x1f) == 0x00) {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_ATAPI_ZIPDISK;
- }
- } else {
- if ((InquiryData[0] & 0x1f) == 0x05) {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_CDROM;
- } else if ((InquiryData[0] & 0x1f) == 0x00) {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_ATAPI_ZIPDISK;
- }
- }
- FreePool (InquiryData);
- } else {
- if (IdeDevice == 0) {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_MASTER_IDE;
- } else {
- LocalHddInfo[PciIndex + IdeChannel].Status |= HDD_SLAVE_IDE;
- }
- }
- }
- }
- }
- if (HandleBuffer != NULL) {
- FreePool (HandleBuffer);
- }
- return EFI_SUCCESS;
- }
- /**
- If the IDE channel is in compatibility (legacy) mode, remove all
- PCI I/O BAR addresses from the controller.
- @param IdeController The handle of target IDE controller
- **/
- VOID
- InitLegacyIdeController (
- IN EFI_HANDLE IdeController
- )
- {
- EFI_PCI_IO_PROTOCOL *PciIo;
- UINT32 IOBarClear;
- EFI_STATUS Status;
- PCI_TYPE00 PciData;
- //
- // If the IDE channel is in compatibility (legacy) mode, remove all
- // PCI I/O BAR addresses from the controller. Some software gets
- // confused if an IDE controller is in compatibility (legacy) mode
- // and has PCI I/O resources allocated
- //
- Status = gBS->HandleProtocol (
- IdeController,
- &gEfiPciIoProtocolGuid,
- (VOID **)&PciIo
- );
- if (EFI_ERROR (Status)) {
- return;
- }
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciData), &PciData);
- if (EFI_ERROR (Status)) {
- return;
- }
- //
- // Check whether this is IDE
- //
- if ((PciData.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE) ||
- (PciData.Hdr.ClassCode[1] != PCI_CLASS_MASS_STORAGE_IDE))
- {
- return;
- }
- //
- // Clear bar for legacy IDE
- //
- IOBarClear = 0x00;
- if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_PNE) == 0) {
- PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear);
- PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear);
- }
- if ((PciData.Hdr.ClassCode[0] & IDE_PI_REGISTER_SNE) == 0) {
- PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear);
- PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear);
- }
- return;
- }
|