2 Collect Sio information from Native EFI Drivers.
3 Sio is floppy, parallel, serial, ... hardware
5 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "LegacyBiosInterface.h"
14 Collect EFI Info about legacy devices through Super IO interface.
16 @param SioPtr Pointer to SIO data.
18 @retval EFI_SUCCESS When SIO data is got successfully.
19 @retval EFI_NOT_FOUND When ISA IO interface is absent.
23 LegacyBiosBuildSioDataFromSio (
24 IN DEVICE_PRODUCER_DATA_HEADER
*SioPtr
28 DEVICE_PRODUCER_SERIAL
*SioSerial
;
29 DEVICE_PRODUCER_PARALLEL
*SioParallel
;
30 DEVICE_PRODUCER_FLOPPY
*SioFloppy
;
32 EFI_HANDLE
*HandleBuffer
;
35 EFI_SIO_PROTOCOL
*Sio
;
36 ACPI_RESOURCE_HEADER_PTR Resources
;
37 EFI_ACPI_IO_PORT_DESCRIPTOR
*IoResource
;
38 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIoResource
;
39 EFI_ACPI_DMA_DESCRIPTOR
*DmaResource
;
40 EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR
*IrqResource
;
45 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
46 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
47 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
48 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
49 ACPI_HID_DEVICE_PATH
*Acpi
;
52 // Get the list of ISA controllers in the system
54 Status
= gBS
->LocateHandleBuffer (
61 if (EFI_ERROR (Status
)) {
65 // Collect legacy information from each of the ISA controllers in the system
67 for (Index
= 0; Index
< HandleCount
; Index
++) {
68 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSioProtocolGuid
, (VOID
**) &Sio
);
69 if (EFI_ERROR (Status
)) {
76 Status
= Sio
->GetResources (Sio
, &Resources
);
77 if (!EFI_ERROR (Status
)) {
79 // Get the base address information from ACPI resource descriptor.
81 while (Resources
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
82 switch (Resources
.SmallHeader
->Byte
) {
83 case ACPI_IO_PORT_DESCRIPTOR
:
84 IoResource
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
85 Address
= IoResource
->BaseAddressMin
;
88 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
89 FixedIoResource
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
90 Address
= FixedIoResource
->BaseAddress
;
93 case ACPI_DMA_DESCRIPTOR
:
94 DmaResource
= (EFI_ACPI_DMA_DESCRIPTOR
*) Resources
.SmallHeader
;
95 Dma
= (UINT8
) LowBitSet32 (DmaResource
->ChannelMask
);
98 case ACPI_IRQ_DESCRIPTOR
:
99 case ACPI_IRQ_NOFLAG_DESCRIPTOR
:
100 IrqResource
= (EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR
*) Resources
.SmallHeader
;
101 Irq
= (UINT8
) LowBitSet32 (IrqResource
->Mask
);
108 if (Resources
.SmallHeader
->Bits
.Type
== 0) {
109 Resources
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) Resources
.SmallHeader
110 + Resources
.SmallHeader
->Bits
.Length
111 + sizeof (*Resources
.SmallHeader
));
113 Resources
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) Resources
.LargeHeader
114 + Resources
.LargeHeader
->Length
115 + sizeof (*Resources
.LargeHeader
));
120 DEBUG ((DEBUG_INFO
, "LegacySio: Address/Dma/Irq = %x/%d/%d\n", Address
, Dma
, Irq
));
122 DevicePath
= DevicePathFromHandle (HandleBuffer
[Index
]);
123 if (DevicePath
== NULL
) {
128 while (!IsDevicePathEnd (DevicePath
)) {
129 Acpi
= (ACPI_HID_DEVICE_PATH
*) DevicePath
;
130 DevicePath
= NextDevicePathNode (DevicePath
);
133 if ((Acpi
== NULL
) || (DevicePathType (Acpi
) != ACPI_DEVICE_PATH
) ||
134 ((DevicePathSubType (Acpi
) != ACPI_DP
) && (DevicePathSubType (Acpi
) != ACPI_EXTENDED_DP
))
140 // See if this is an ISA serial port
142 // Ignore DMA resource since it is always returned NULL
144 if (Acpi
->HID
== EISA_PNP_ID (0x500) || Acpi
->HID
== EISA_PNP_ID (0x501)) {
146 if (Acpi
->UID
< 4 && Address
!= MAX_UINT16
&& Irq
!= MAX_UINT8
) {
148 // Get the handle of the child device that has opened the Super I/O Protocol
150 Status
= gBS
->OpenProtocolInformation (
152 &gEfiSioProtocolGuid
,
156 if (EFI_ERROR (Status
)) {
159 for (ChildIndex
= 0; ChildIndex
< EntryCount
; ChildIndex
++) {
160 if ((OpenInfoBuffer
[ChildIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
161 Status
= gBS
->HandleProtocol (OpenInfoBuffer
[ChildIndex
].ControllerHandle
, &gEfiSerialIoProtocolGuid
, (VOID
**) &SerialIo
);
162 if (!EFI_ERROR (Status
)) {
163 SioSerial
= &SioPtr
->Serial
[Acpi
->UID
];
164 SioSerial
->Address
= Address
;
165 SioSerial
->Irq
= Irq
;
166 SioSerial
->Mode
= DEVICE_SERIAL_MODE_NORMAL
| DEVICE_SERIAL_MODE_DUPLEX_HALF
;
172 FreePool (OpenInfoBuffer
);
176 // See if this is an ISA parallel port
178 // Ignore DMA resource since it is always returned NULL, port
179 // only used in output mode.
181 if (Acpi
->HID
== EISA_PNP_ID (0x400) || Acpi
->HID
== EISA_PNP_ID (0x401)) {
182 if (Acpi
->UID
< 3 && Address
!= MAX_UINT16
&& Irq
!= MAX_UINT8
&& Dma
!= MAX_UINT8
) {
183 SioParallel
= &SioPtr
->Parallel
[Acpi
->UID
];
184 SioParallel
->Address
= Address
;
185 SioParallel
->Irq
= Irq
;
186 SioParallel
->Dma
= Dma
;
187 SioParallel
->Mode
= DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY
;
191 // See if this is an ISA floppy controller
193 if (Acpi
->HID
== EISA_PNP_ID (0x604)) {
194 if (Address
!= MAX_UINT16
&& Irq
!= MAX_UINT8
&& Dma
!= MAX_UINT8
) {
195 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiBlockIoProtocolGuid
, (VOID
**) &BlockIo
);
196 if (!EFI_ERROR (Status
)) {
197 SioFloppy
= &SioPtr
->Floppy
;
198 SioFloppy
->Address
= Address
;
199 SioFloppy
->Irq
= Irq
;
200 SioFloppy
->Dma
= Dma
;
201 SioFloppy
->NumberOfFloppy
++;
206 // See if this is a mouse
207 // Always set mouse found so USB hot plug will work
209 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
211 // Hid = ResourceList->Device.HID & 0xff00ffff;
212 // PnpId = EISA_PNP_ID(0x0f00);
213 // if (Hid == PnpId) {
214 // if (ResourceList->Device.UID == 1) {
215 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
216 // if (!EFI_ERROR (Status)) {
218 SioPtr
->MousePresent
= 0x01;
226 FreePool (HandleBuffer
);
232 Collect EFI Info about legacy devices through ISA IO interface.
234 @param SioPtr Pointer to SIO data.
236 @retval EFI_SUCCESS When SIO data is got successfully.
237 @retval EFI_NOT_FOUND When ISA IO interface is absent.
241 LegacyBiosBuildSioDataFromIsaIo (
242 IN DEVICE_PRODUCER_DATA_HEADER
*SioPtr
246 DEVICE_PRODUCER_SERIAL
*SioSerial
;
247 DEVICE_PRODUCER_PARALLEL
*SioParallel
;
248 DEVICE_PRODUCER_FLOPPY
*SioFloppy
;
250 EFI_HANDLE
*HandleBuffer
;
254 EFI_ISA_IO_PROTOCOL
*IsaIo
;
255 EFI_ISA_ACPI_RESOURCE_LIST
*ResourceList
;
256 EFI_ISA_ACPI_RESOURCE
*IoResource
;
257 EFI_ISA_ACPI_RESOURCE
*DmaResource
;
258 EFI_ISA_ACPI_RESOURCE
*InterruptResource
;
260 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
261 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
262 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
265 // Get the list of ISA controllers in the system
267 Status
= gBS
->LocateHandleBuffer (
269 &gEfiIsaIoProtocolGuid
,
274 if (EFI_ERROR (Status
)) {
275 return EFI_NOT_FOUND
;
278 // Collect legacy information from each of the ISA controllers in the system
280 for (Index
= 0; Index
< HandleCount
; Index
++) {
282 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiIsaIoProtocolGuid
, (VOID
**) &IsaIo
);
283 if (EFI_ERROR (Status
)) {
287 ResourceList
= IsaIo
->ResourceList
;
289 if (ResourceList
== NULL
) {
293 // Collect the resource types neededto fill in the SIO data structure
297 InterruptResource
= NULL
;
298 for (ResourceIndex
= 0;
299 ResourceList
->ResourceItem
[ResourceIndex
].Type
!= EfiIsaAcpiResourceEndOfList
;
302 switch (ResourceList
->ResourceItem
[ResourceIndex
].Type
) {
303 case EfiIsaAcpiResourceIo
:
304 IoResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
307 case EfiIsaAcpiResourceMemory
:
310 case EfiIsaAcpiResourceDma
:
311 DmaResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
314 case EfiIsaAcpiResourceInterrupt
:
315 InterruptResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
323 // See if this is an ISA serial port
325 // Ignore DMA resource since it is always returned NULL
327 if (ResourceList
->Device
.HID
== EISA_PNP_ID (0x500) || ResourceList
->Device
.HID
== EISA_PNP_ID (0x501)) {
329 if (ResourceList
->Device
.UID
<= 3 &&
330 IoResource
!= NULL
&&
331 InterruptResource
!= NULL
334 // Get the handle of the child device that has opened the ISA I/O Protocol
336 Status
= gBS
->OpenProtocolInformation (
338 &gEfiIsaIoProtocolGuid
,
342 if (EFI_ERROR (Status
)) {
346 // We want resource for legacy even if no 32-bit driver installed
348 for (ChildIndex
= 0; ChildIndex
< EntryCount
; ChildIndex
++) {
349 if ((OpenInfoBuffer
[ChildIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
350 Status
= gBS
->HandleProtocol (OpenInfoBuffer
[ChildIndex
].ControllerHandle
, &gEfiSerialIoProtocolGuid
, (VOID
**) &SerialIo
);
351 if (!EFI_ERROR (Status
)) {
352 SioSerial
= &SioPtr
->Serial
[ResourceList
->Device
.UID
];
353 SioSerial
->Address
= (UINT16
) IoResource
->StartRange
;
354 SioSerial
->Irq
= (UINT8
) InterruptResource
->StartRange
;
355 SioSerial
->Mode
= DEVICE_SERIAL_MODE_NORMAL
| DEVICE_SERIAL_MODE_DUPLEX_HALF
;
361 FreePool (OpenInfoBuffer
);
365 // See if this is an ISA parallel port
367 // Ignore DMA resource since it is always returned NULL, port
368 // only used in output mode.
370 if (ResourceList
->Device
.HID
== EISA_PNP_ID (0x400) || ResourceList
->Device
.HID
== EISA_PNP_ID (0x401)) {
371 if (ResourceList
->Device
.UID
<= 2 &&
372 IoResource
!= NULL
&&
373 InterruptResource
!= NULL
&&
376 SioParallel
= &SioPtr
->Parallel
[ResourceList
->Device
.UID
];
377 SioParallel
->Address
= (UINT16
) IoResource
->StartRange
;
378 SioParallel
->Irq
= (UINT8
) InterruptResource
->StartRange
;
379 SioParallel
->Dma
= (UINT8
) DmaResource
->StartRange
;
380 SioParallel
->Mode
= DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY
;
384 // See if this is an ISA floppy controller
386 if (ResourceList
->Device
.HID
== EISA_PNP_ID (0x604)) {
387 if (IoResource
!= NULL
&& InterruptResource
!= NULL
&& DmaResource
!= NULL
) {
388 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiBlockIoProtocolGuid
, (VOID
**) &BlockIo
);
389 if (!EFI_ERROR (Status
)) {
390 SioFloppy
= &SioPtr
->Floppy
;
391 SioFloppy
->Address
= (UINT16
) IoResource
->StartRange
;
392 SioFloppy
->Irq
= (UINT8
) InterruptResource
->StartRange
;
393 SioFloppy
->Dma
= (UINT8
) DmaResource
->StartRange
;
394 SioFloppy
->NumberOfFloppy
++;
399 // See if this is a mouse
400 // Always set mouse found so USB hot plug will work
402 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
404 // Hid = ResourceList->Device.HID & 0xff00ffff;
405 // PnpId = EISA_PNP_ID(0x0f00);
406 // if (Hid == PnpId) {
407 // if (ResourceList->Device.UID == 1) {
408 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
409 // if (!EFI_ERROR (Status)) {
411 SioPtr
->MousePresent
= 0x01;
419 FreePool (HandleBuffer
);
424 Collect EFI Info about legacy devices.
426 @param Private Legacy BIOS Instance data
428 @retval EFI_SUCCESS It should always work.
432 LegacyBiosBuildSioData (
433 IN LEGACY_BIOS_INSTANCE
*Private
437 DEVICE_PRODUCER_DATA_HEADER
*SioPtr
;
438 EFI_HANDLE IsaBusController
;
440 EFI_HANDLE
*HandleBuffer
;
443 // Get the pointer to the SIO data structure
445 SioPtr
= &Private
->IntThunk
->EfiToLegacy16BootTable
.SioData
;
448 // Zero the data in the SIO data structure
450 gBS
->SetMem (SioPtr
, sizeof (DEVICE_PRODUCER_DATA_HEADER
), 0);
453 // Find the ISA Bus Controller used for legacy
455 Status
= Private
->LegacyBiosPlatform
->GetPlatformHandle (
456 Private
->LegacyBiosPlatform
,
457 EfiGetPlatformIsaBusHandle
,
463 IsaBusController
= HandleBuffer
[0];
464 if (!EFI_ERROR (Status
)) {
466 // Force ISA Bus Controller to produce all ISA devices
468 gBS
->ConnectController (IsaBusController
, NULL
, NULL
, TRUE
);
471 Status
= LegacyBiosBuildSioDataFromIsaIo (SioPtr
);
472 if (EFI_ERROR (Status
)) {
473 LegacyBiosBuildSioDataFromSio (SioPtr
);