From 62ade6d23362e7555572291ef82fdea122c624e4 Mon Sep 17 00:00:00 2001 From: Ruiyu Ni Date: Sun, 12 Jun 2016 16:07:34 +0800 Subject: [PATCH] IntelFrameworkModulePkg/LegacyBios: Get SIO data from SIO interface Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni Reviewed-by: Eric Dong --- .../Csm/LegacyBiosDxe/LegacyBiosDxe.inf | 1 + .../Csm/LegacyBiosDxe/LegacyBiosInterface.h | 2 + .../Csm/LegacyBiosDxe/LegacySio.c | 222 +++++++++++++++++- 3 files changed, 224 insertions(+), 1 deletion(-) diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf index 9090c912aa..430b7fa3c3 100644 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf +++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf @@ -134,6 +134,7 @@ gEfiLegacyRegion2ProtocolGuid ## CONSUMES gEfiLegacyBiosProtocolGuid ## PRODUCES gEfiSerialIoProtocolGuid ## CONSUMES + gEfiSioProtocolGuid ## CONSUMES [Pcd] gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLegacyBiosCacheLegacyRegion ## CONSUMES diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h index 3869e06718..bbd074b56c 100644 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h +++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosInterface.h @@ -20,6 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include @@ -45,6 +46,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include diff --git a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c index a27a477eaa..c853377192 100644 --- a/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c +++ b/IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacySio.c @@ -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; } -- 2.39.2