IntelFrameworkModulePkg/LegacyBios: Get SIO data from SIO interface

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
This commit is contained in:
Ruiyu Ni 2016-06-12 16:07:34 +08:00
parent faef695239
commit 62ade6d233
3 changed files with 224 additions and 1 deletions

View File

@ -134,6 +134,7 @@
gEfiLegacyRegion2ProtocolGuid ## CONSUMES
gEfiLegacyBiosProtocolGuid ## PRODUCES
gEfiSerialIoProtocolGuid ## CONSUMES
gEfiSioProtocolGuid ## CONSUMES
[Pcd]
gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion ## CONSUMES

View File

@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <FrameworkDxe.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/SmBios.h>
#include <IndustryStandard/Acpi10.h>
#include <Guid/SmBios.h>
#include <Guid/Acpi.h>
@ -45,6 +46,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/Legacy8259.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/SerialIo.h>
#include <Protocol/SuperIo.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>

View File

@ -17,6 +17,223 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "LegacyBiosInterface.h"
/**
Collect EFI Info about legacy devices through Super IO interface.
@param SioPtr Pointer to SIO data.
@retval EFI_SUCCESS When SIO data is got successfully.
@retval EFI_NOT_FOUND When ISA IO interface is absent.
**/
EFI_STATUS
LegacyBiosBuildSioDataFromSio (
IN DEVICE_PRODUCER_DATA_HEADER *SioPtr
)
{
EFI_STATUS Status;
DEVICE_PRODUCER_SERIAL *SioSerial;
DEVICE_PRODUCER_PARALLEL *SioParallel;
DEVICE_PRODUCER_FLOPPY *SioFloppy;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINTN Index;
UINTN ChildIndex;
EFI_SIO_PROTOCOL *Sio;
ACPI_RESOURCE_HEADER_PTR Resources;
EFI_ACPI_IO_PORT_DESCRIPTOR *IoResource;
EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIoResource;
EFI_ACPI_DMA_DESCRIPTOR *DmaResource;
EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR *IrqResource;
UINT16 Address;
UINT8 Dma;
UINT8 Irq;
UINTN EntryCount;
EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
EFI_BLOCK_IO_PROTOCOL *BlockIo;
EFI_SERIAL_IO_PROTOCOL *SerialIo;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
ACPI_HID_DEVICE_PATH *Acpi;
//
// Get the list of ISA controllers in the system
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSioProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return EFI_NOT_FOUND;
}
//
// Collect legacy information from each of the ISA controllers in the system
//
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSioProtocolGuid, (VOID **) &Sio);
if (EFI_ERROR (Status)) {
continue;
}
Address = MAX_UINT16;
Dma = MAX_UINT8;
Irq = MAX_UINT8;
Status = Sio->GetResources (Sio, &Resources);
if (!EFI_ERROR (Status)) {
//
// Get the base address information from ACPI resource descriptor.
//
while (Resources.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {
switch (Resources.SmallHeader->Byte) {
case ACPI_IO_PORT_DESCRIPTOR:
IoResource = (EFI_ACPI_IO_PORT_DESCRIPTOR *) Resources.SmallHeader;
Address = IoResource->BaseAddressMin;
break;
case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR:
FixedIoResource = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *) Resources.SmallHeader;
Address = FixedIoResource->BaseAddress;
break;
case ACPI_DMA_DESCRIPTOR:
DmaResource = (EFI_ACPI_DMA_DESCRIPTOR *) Resources.SmallHeader;
Dma = (UINT8) LowBitSet32 (DmaResource->ChannelMask);
break;
case ACPI_IRQ_DESCRIPTOR:
case ACPI_IRQ_NOFLAG_DESCRIPTOR:
IrqResource = (EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR *) Resources.SmallHeader;
Irq = (UINT8) LowBitSet32 (IrqResource->Mask);
break;
default:
break;
}
if (Resources.SmallHeader->Bits.Type == 0) {
Resources.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *) ((UINT8 *) Resources.SmallHeader
+ Resources.SmallHeader->Bits.Length
+ sizeof (*Resources.SmallHeader));
} else {
Resources.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *) ((UINT8 *) Resources.LargeHeader
+ Resources.LargeHeader->Length
+ sizeof (*Resources.LargeHeader));
}
}
}
DEBUG ((EFI_D_INFO, "LegacySio: Address/Dma/Irq = %x/%d/%d\n", Address, Dma, Irq));
DevicePath = DevicePathFromHandle (HandleBuffer[Index]);
if (DevicePath == NULL) {
continue;
}
Acpi = NULL;
while (!IsDevicePathEnd (DevicePath)) {
Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
DevicePath = NextDevicePathNode (DevicePath);
}
if ((Acpi == NULL) || (DevicePathType (Acpi) != ACPI_DEVICE_PATH) ||
((DevicePathSubType (Acpi) != ACPI_DP) && (DevicePathSubType (Acpi) != ACPI_EXTENDED_DP))
) {
continue;
}
//
// See if this is an ISA serial port
//
// Ignore DMA resource since it is always returned NULL
//
if (Acpi->HID == EISA_PNP_ID (0x500) || Acpi->HID == EISA_PNP_ID (0x501)) {
if (Acpi->UID < 4 && Address != MAX_UINT16 && Irq != MAX_UINT8) {
//
// Get the handle of the child device that has opened the Super I/O Protocol
//
Status = gBS->OpenProtocolInformation (
HandleBuffer[Index],
&gEfiSioProtocolGuid,
&OpenInfoBuffer,
&EntryCount
);
if (EFI_ERROR (Status)) {
continue;
}
for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {
if ((OpenInfoBuffer[ChildIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
Status = gBS->HandleProtocol (OpenInfoBuffer[ChildIndex].ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **) &SerialIo);
if (!EFI_ERROR (Status)) {
SioSerial = &SioPtr->Serial[Acpi->UID];
SioSerial->Address = Address;
SioSerial->Irq = Irq;
SioSerial->Mode = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;
break;
}
}
}
FreePool (OpenInfoBuffer);
}
}
//
// See if this is an ISA parallel port
//
// Ignore DMA resource since it is always returned NULL, port
// only used in output mode.
//
if (Acpi->HID == EISA_PNP_ID (0x400) || Acpi->HID == EISA_PNP_ID (0x401)) {
if (Acpi->UID < 3 && Address != MAX_UINT16 && Irq != MAX_UINT8 && Dma != MAX_UINT8) {
SioParallel = &SioPtr->Parallel[Acpi->UID];
SioParallel->Address = Address;
SioParallel->Irq = Irq;
SioParallel->Dma = Dma;
SioParallel->Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;
}
}
//
// See if this is an ISA floppy controller
//
if (Acpi->HID == EISA_PNP_ID (0x604)) {
if (Address != MAX_UINT16 && Irq != MAX_UINT8 && Dma != MAX_UINT8) {
Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);
if (!EFI_ERROR (Status)) {
SioFloppy = &SioPtr->Floppy;
SioFloppy->Address = Address;
SioFloppy->Irq = Irq;
SioFloppy->Dma = Dma;
SioFloppy->NumberOfFloppy++;
}
}
}
//
// See if this is a mouse
// Always set mouse found so USB hot plug will work
//
// Ignore lower byte of HID. Pnp0fxx is any type of mouse.
//
// Hid = ResourceList->Device.HID & 0xff00ffff;
// PnpId = EISA_PNP_ID(0x0f00);
// if (Hid == PnpId) {
// if (ResourceList->Device.UID == 1) {
// Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
// if (!EFI_ERROR (Status)) {
//
SioPtr->MousePresent = 0x01;
//
// }
// }
// }
//
}
FreePool (HandleBuffer);
return EFI_SUCCESS;
}
/**
Collect EFI Info about legacy devices through ISA IO interface.
@ -258,7 +475,10 @@ LegacyBiosBuildSioData (
gBS->ConnectController (IsaBusController, NULL, NULL, TRUE);
}
LegacyBiosBuildSioDataFromIsaIo (SioPtr);
Status = LegacyBiosBuildSioDataFromIsaIo (SioPtr);
if (EFI_ERROR (Status)) {
LegacyBiosBuildSioDataFromSio (SioPtr);
}
return EFI_SUCCESS;
}