Added these drivers: * LegacyBiosDxe * BlockIoDxe * KeyboardDxe * Snp16Dxe * VideoDxe Signed-off-by: jljusten Reviewed-by: mdkinney Reviewed-by: geekboy15a git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11905 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			301 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Collect IDE information from Native EFI Driver
 | 
						|
 | 
						|
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
 | 
						|
 | 
						|
This program and the accompanying materials
 | 
						|
are licensed and made available under the terms and conditions
 | 
						|
of the BSD License which accompanies this distribution.  The
 | 
						|
full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#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;
 | 
						|
  UINT8                             Pi;
 | 
						|
  UINT32                            IOBarClear;
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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)) {
 | 
						|
    IOBarClear = 0x00;
 | 
						|
    PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 1, &Pi);
 | 
						|
    if ((Pi & 0x01) == 0) {
 | 
						|
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x10, 1, &IOBarClear);
 | 
						|
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x14, 1, &IOBarClear);
 | 
						|
    }
 | 
						|
    if ((Pi & 0x04) == 0) {
 | 
						|
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x18, 1, &IOBarClear);
 | 
						|
      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1C, 1, &IOBarClear);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ;
 | 
						|
}
 |