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
)) {
66 // Collect legacy information from each of the ISA controllers in the system
68 for (Index
= 0; Index
< HandleCount
; Index
++) {
69 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSioProtocolGuid
, (VOID
**)&Sio
);
70 if (EFI_ERROR (Status
)) {
77 Status
= Sio
->GetResources (Sio
, &Resources
);
78 if (!EFI_ERROR (Status
)) {
80 // Get the base address information from ACPI resource descriptor.
82 while (Resources
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
83 switch (Resources
.SmallHeader
->Byte
) {
84 case ACPI_IO_PORT_DESCRIPTOR
:
85 IoResource
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*)Resources
.SmallHeader
;
86 Address
= IoResource
->BaseAddressMin
;
89 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
90 FixedIoResource
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*)Resources
.SmallHeader
;
91 Address
= FixedIoResource
->BaseAddress
;
94 case ACPI_DMA_DESCRIPTOR
:
95 DmaResource
= (EFI_ACPI_DMA_DESCRIPTOR
*)Resources
.SmallHeader
;
96 Dma
= (UINT8
)LowBitSet32 (DmaResource
->ChannelMask
);
99 case ACPI_IRQ_DESCRIPTOR
:
100 case ACPI_IRQ_NOFLAG_DESCRIPTOR
:
101 IrqResource
= (EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR
*)Resources
.SmallHeader
;
102 Irq
= (UINT8
)LowBitSet32 (IrqResource
->Mask
);
109 if (Resources
.SmallHeader
->Bits
.Type
== 0) {
110 Resources
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*)((UINT8
*)Resources
.SmallHeader
111 + Resources
.SmallHeader
->Bits
.Length
112 + sizeof (*Resources
.SmallHeader
));
114 Resources
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*)((UINT8
*)Resources
.LargeHeader
115 + Resources
.LargeHeader
->Length
116 + sizeof (*Resources
.LargeHeader
));
121 DEBUG ((DEBUG_INFO
, "LegacySio: Address/Dma/Irq = %x/%d/%d\n", Address
, Dma
, Irq
));
123 DevicePath
= DevicePathFromHandle (HandleBuffer
[Index
]);
124 if (DevicePath
== NULL
) {
129 while (!IsDevicePathEnd (DevicePath
)) {
130 Acpi
= (ACPI_HID_DEVICE_PATH
*)DevicePath
;
131 DevicePath
= NextDevicePathNode (DevicePath
);
134 if ((Acpi
== NULL
) || (DevicePathType (Acpi
) != ACPI_DEVICE_PATH
) ||
135 ((DevicePathSubType (Acpi
) != ACPI_DP
) && (DevicePathSubType (Acpi
) != ACPI_EXTENDED_DP
))
142 // See if this is an ISA serial port
144 // Ignore DMA resource since it is always returned NULL
146 if ((Acpi
->HID
== EISA_PNP_ID (0x500)) || (Acpi
->HID
== EISA_PNP_ID (0x501))) {
147 if ((Acpi
->UID
< 4) && (Address
!= MAX_UINT16
) && (Irq
!= MAX_UINT8
)) {
149 // Get the handle of the child device that has opened the Super I/O Protocol
151 Status
= gBS
->OpenProtocolInformation (
153 &gEfiSioProtocolGuid
,
157 if (EFI_ERROR (Status
)) {
161 for (ChildIndex
= 0; ChildIndex
< EntryCount
; ChildIndex
++) {
162 if ((OpenInfoBuffer
[ChildIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
163 Status
= gBS
->HandleProtocol (OpenInfoBuffer
[ChildIndex
].ControllerHandle
, &gEfiSerialIoProtocolGuid
, (VOID
**)&SerialIo
);
164 if (!EFI_ERROR (Status
)) {
165 SioSerial
= &SioPtr
->Serial
[Acpi
->UID
];
166 SioSerial
->Address
= Address
;
167 SioSerial
->Irq
= Irq
;
168 SioSerial
->Mode
= DEVICE_SERIAL_MODE_NORMAL
| DEVICE_SERIAL_MODE_DUPLEX_HALF
;
174 FreePool (OpenInfoBuffer
);
179 // See if this is an ISA parallel port
181 // Ignore DMA resource since it is always returned NULL, port
182 // only used in output mode.
184 if ((Acpi
->HID
== EISA_PNP_ID (0x400)) || (Acpi
->HID
== EISA_PNP_ID (0x401))) {
185 if ((Acpi
->UID
< 3) && (Address
!= MAX_UINT16
) && (Irq
!= MAX_UINT8
) && (Dma
!= MAX_UINT8
)) {
186 SioParallel
= &SioPtr
->Parallel
[Acpi
->UID
];
187 SioParallel
->Address
= Address
;
188 SioParallel
->Irq
= Irq
;
189 SioParallel
->Dma
= Dma
;
190 SioParallel
->Mode
= DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY
;
195 // See if this is an ISA floppy controller
197 if (Acpi
->HID
== EISA_PNP_ID (0x604)) {
198 if ((Address
!= MAX_UINT16
) && (Irq
!= MAX_UINT8
) && (Dma
!= MAX_UINT8
)) {
199 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiBlockIoProtocolGuid
, (VOID
**)&BlockIo
);
200 if (!EFI_ERROR (Status
)) {
201 SioFloppy
= &SioPtr
->Floppy
;
202 SioFloppy
->Address
= Address
;
203 SioFloppy
->Irq
= Irq
;
204 SioFloppy
->Dma
= Dma
;
205 SioFloppy
->NumberOfFloppy
++;
211 // See if this is a mouse
212 // Always set mouse found so USB hot plug will work
214 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
216 // Hid = ResourceList->Device.HID & 0xff00ffff;
217 // PnpId = EISA_PNP_ID(0x0f00);
218 // if (Hid == PnpId) {
219 // if (ResourceList->Device.UID == 1) {
220 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
221 // if (!EFI_ERROR (Status)) {
223 SioPtr
->MousePresent
= 0x01;
231 FreePool (HandleBuffer
);
236 Collect EFI Info about legacy devices through ISA IO interface.
238 @param SioPtr Pointer to SIO data.
240 @retval EFI_SUCCESS When SIO data is got successfully.
241 @retval EFI_NOT_FOUND When ISA IO interface is absent.
245 LegacyBiosBuildSioDataFromIsaIo (
246 IN DEVICE_PRODUCER_DATA_HEADER
*SioPtr
250 DEVICE_PRODUCER_SERIAL
*SioSerial
;
251 DEVICE_PRODUCER_PARALLEL
*SioParallel
;
252 DEVICE_PRODUCER_FLOPPY
*SioFloppy
;
254 EFI_HANDLE
*HandleBuffer
;
258 EFI_ISA_IO_PROTOCOL
*IsaIo
;
259 EFI_ISA_ACPI_RESOURCE_LIST
*ResourceList
;
260 EFI_ISA_ACPI_RESOURCE
*IoResource
;
261 EFI_ISA_ACPI_RESOURCE
*DmaResource
;
262 EFI_ISA_ACPI_RESOURCE
*InterruptResource
;
264 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
265 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
266 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
269 // Get the list of ISA controllers in the system
271 Status
= gBS
->LocateHandleBuffer (
273 &gEfiIsaIoProtocolGuid
,
278 if (EFI_ERROR (Status
)) {
279 return EFI_NOT_FOUND
;
283 // Collect legacy information from each of the ISA controllers in the system
285 for (Index
= 0; Index
< HandleCount
; Index
++) {
286 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiIsaIoProtocolGuid
, (VOID
**)&IsaIo
);
287 if (EFI_ERROR (Status
)) {
291 ResourceList
= IsaIo
->ResourceList
;
293 if (ResourceList
== NULL
) {
298 // Collect the resource types neededto fill in the SIO data structure
302 InterruptResource
= NULL
;
303 for (ResourceIndex
= 0;
304 ResourceList
->ResourceItem
[ResourceIndex
].Type
!= EfiIsaAcpiResourceEndOfList
;
308 switch (ResourceList
->ResourceItem
[ResourceIndex
].Type
) {
309 case EfiIsaAcpiResourceIo
:
310 IoResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
313 case EfiIsaAcpiResourceMemory
:
316 case EfiIsaAcpiResourceDma
:
317 DmaResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
320 case EfiIsaAcpiResourceInterrupt
:
321 InterruptResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
330 // See if this is an ISA serial port
332 // Ignore DMA resource since it is always returned NULL
334 if ((ResourceList
->Device
.HID
== EISA_PNP_ID (0x500)) || (ResourceList
->Device
.HID
== EISA_PNP_ID (0x501))) {
335 if ((ResourceList
->Device
.UID
<= 3) &&
336 (IoResource
!= NULL
) &&
337 (InterruptResource
!= NULL
)
341 // Get the handle of the child device that has opened the ISA I/O Protocol
343 Status
= gBS
->OpenProtocolInformation (
345 &gEfiIsaIoProtocolGuid
,
349 if (EFI_ERROR (Status
)) {
354 // We want resource for legacy even if no 32-bit driver installed
356 for (ChildIndex
= 0; ChildIndex
< EntryCount
; ChildIndex
++) {
357 if ((OpenInfoBuffer
[ChildIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
358 Status
= gBS
->HandleProtocol (OpenInfoBuffer
[ChildIndex
].ControllerHandle
, &gEfiSerialIoProtocolGuid
, (VOID
**)&SerialIo
);
359 if (!EFI_ERROR (Status
)) {
360 SioSerial
= &SioPtr
->Serial
[ResourceList
->Device
.UID
];
361 SioSerial
->Address
= (UINT16
)IoResource
->StartRange
;
362 SioSerial
->Irq
= (UINT8
)InterruptResource
->StartRange
;
363 SioSerial
->Mode
= DEVICE_SERIAL_MODE_NORMAL
| DEVICE_SERIAL_MODE_DUPLEX_HALF
;
369 FreePool (OpenInfoBuffer
);
374 // See if this is an ISA parallel port
376 // Ignore DMA resource since it is always returned NULL, port
377 // only used in output mode.
379 if ((ResourceList
->Device
.HID
== EISA_PNP_ID (0x400)) || (ResourceList
->Device
.HID
== EISA_PNP_ID (0x401))) {
380 if ((ResourceList
->Device
.UID
<= 2) &&
381 (IoResource
!= NULL
) &&
382 (InterruptResource
!= NULL
) &&
383 (DmaResource
!= NULL
)
386 SioParallel
= &SioPtr
->Parallel
[ResourceList
->Device
.UID
];
387 SioParallel
->Address
= (UINT16
)IoResource
->StartRange
;
388 SioParallel
->Irq
= (UINT8
)InterruptResource
->StartRange
;
389 SioParallel
->Dma
= (UINT8
)DmaResource
->StartRange
;
390 SioParallel
->Mode
= DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY
;
395 // See if this is an ISA floppy controller
397 if (ResourceList
->Device
.HID
== EISA_PNP_ID (0x604)) {
398 if ((IoResource
!= NULL
) && (InterruptResource
!= NULL
) && (DmaResource
!= NULL
)) {
399 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiBlockIoProtocolGuid
, (VOID
**)&BlockIo
);
400 if (!EFI_ERROR (Status
)) {
401 SioFloppy
= &SioPtr
->Floppy
;
402 SioFloppy
->Address
= (UINT16
)IoResource
->StartRange
;
403 SioFloppy
->Irq
= (UINT8
)InterruptResource
->StartRange
;
404 SioFloppy
->Dma
= (UINT8
)DmaResource
->StartRange
;
405 SioFloppy
->NumberOfFloppy
++;
411 // See if this is a mouse
412 // Always set mouse found so USB hot plug will work
414 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
416 // Hid = ResourceList->Device.HID & 0xff00ffff;
417 // PnpId = EISA_PNP_ID(0x0f00);
418 // if (Hid == PnpId) {
419 // if (ResourceList->Device.UID == 1) {
420 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
421 // if (!EFI_ERROR (Status)) {
423 SioPtr
->MousePresent
= 0x01;
431 FreePool (HandleBuffer
);
436 Collect EFI Info about legacy devices.
438 @param Private Legacy BIOS Instance data
440 @retval EFI_SUCCESS It should always work.
444 LegacyBiosBuildSioData (
445 IN LEGACY_BIOS_INSTANCE
*Private
449 DEVICE_PRODUCER_DATA_HEADER
*SioPtr
;
450 EFI_HANDLE IsaBusController
;
452 EFI_HANDLE
*HandleBuffer
;
455 // Get the pointer to the SIO data structure
457 SioPtr
= &Private
->IntThunk
->EfiToLegacy16BootTable
.SioData
;
460 // Zero the data in the SIO data structure
462 gBS
->SetMem (SioPtr
, sizeof (DEVICE_PRODUCER_DATA_HEADER
), 0);
465 // Find the ISA Bus Controller used for legacy
467 Status
= Private
->LegacyBiosPlatform
->GetPlatformHandle (
468 Private
->LegacyBiosPlatform
,
469 EfiGetPlatformIsaBusHandle
,
475 IsaBusController
= HandleBuffer
[0];
476 if (!EFI_ERROR (Status
)) {
478 // Force ISA Bus Controller to produce all ISA devices
480 gBS
->ConnectController (IsaBusController
, NULL
, NULL
, TRUE
);
483 Status
= LegacyBiosBuildSioDataFromIsaIo (SioPtr
);
484 if (EFI_ERROR (Status
)) {
485 LegacyBiosBuildSioDataFromSio (SioPtr
);