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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution. The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "LegacyBiosInterface.h"
21 Collect EFI Info about legacy devices through Super IO interface.
23 @param SioPtr Pointer to SIO data.
25 @retval EFI_SUCCESS When SIO data is got successfully.
26 @retval EFI_NOT_FOUND When ISA IO interface is absent.
30 LegacyBiosBuildSioDataFromSio (
31 IN DEVICE_PRODUCER_DATA_HEADER
*SioPtr
35 DEVICE_PRODUCER_SERIAL
*SioSerial
;
36 DEVICE_PRODUCER_PARALLEL
*SioParallel
;
37 DEVICE_PRODUCER_FLOPPY
*SioFloppy
;
39 EFI_HANDLE
*HandleBuffer
;
42 EFI_SIO_PROTOCOL
*Sio
;
43 ACPI_RESOURCE_HEADER_PTR Resources
;
44 EFI_ACPI_IO_PORT_DESCRIPTOR
*IoResource
;
45 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*FixedIoResource
;
46 EFI_ACPI_DMA_DESCRIPTOR
*DmaResource
;
47 EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR
*IrqResource
;
52 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
53 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
54 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
55 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
56 ACPI_HID_DEVICE_PATH
*Acpi
;
59 // Get the list of ISA controllers in the system
61 Status
= gBS
->LocateHandleBuffer (
68 if (EFI_ERROR (Status
)) {
72 // Collect legacy information from each of the ISA controllers in the system
74 for (Index
= 0; Index
< HandleCount
; Index
++) {
75 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSioProtocolGuid
, (VOID
**) &Sio
);
76 if (EFI_ERROR (Status
)) {
83 Status
= Sio
->GetResources (Sio
, &Resources
);
84 if (!EFI_ERROR (Status
)) {
86 // Get the base address information from ACPI resource descriptor.
88 while (Resources
.SmallHeader
->Byte
!= ACPI_END_TAG_DESCRIPTOR
) {
89 switch (Resources
.SmallHeader
->Byte
) {
90 case ACPI_IO_PORT_DESCRIPTOR
:
91 IoResource
= (EFI_ACPI_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
92 Address
= IoResource
->BaseAddressMin
;
95 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
:
96 FixedIoResource
= (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR
*) Resources
.SmallHeader
;
97 Address
= FixedIoResource
->BaseAddress
;
100 case ACPI_DMA_DESCRIPTOR
:
101 DmaResource
= (EFI_ACPI_DMA_DESCRIPTOR
*) Resources
.SmallHeader
;
102 Dma
= (UINT8
) LowBitSet32 (DmaResource
->ChannelMask
);
105 case ACPI_IRQ_DESCRIPTOR
:
106 case ACPI_IRQ_NOFLAG_DESCRIPTOR
:
107 IrqResource
= (EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR
*) Resources
.SmallHeader
;
108 Irq
= (UINT8
) LowBitSet32 (IrqResource
->Mask
);
115 if (Resources
.SmallHeader
->Bits
.Type
== 0) {
116 Resources
.SmallHeader
= (ACPI_SMALL_RESOURCE_HEADER
*) ((UINT8
*) Resources
.SmallHeader
117 + Resources
.SmallHeader
->Bits
.Length
118 + sizeof (*Resources
.SmallHeader
));
120 Resources
.LargeHeader
= (ACPI_LARGE_RESOURCE_HEADER
*) ((UINT8
*) Resources
.LargeHeader
121 + Resources
.LargeHeader
->Length
122 + sizeof (*Resources
.LargeHeader
));
127 DEBUG ((EFI_D_INFO
, "LegacySio: Address/Dma/Irq = %x/%d/%d\n", Address
, Dma
, Irq
));
129 DevicePath
= DevicePathFromHandle (HandleBuffer
[Index
]);
130 if (DevicePath
== NULL
) {
135 while (!IsDevicePathEnd (DevicePath
)) {
136 Acpi
= (ACPI_HID_DEVICE_PATH
*) DevicePath
;
137 DevicePath
= NextDevicePathNode (DevicePath
);
140 if ((Acpi
== NULL
) || (DevicePathType (Acpi
) != ACPI_DEVICE_PATH
) ||
141 ((DevicePathSubType (Acpi
) != ACPI_DP
) && (DevicePathSubType (Acpi
) != ACPI_EXTENDED_DP
))
147 // See if this is an ISA serial port
149 // Ignore DMA resource since it is always returned NULL
151 if (Acpi
->HID
== EISA_PNP_ID (0x500) || Acpi
->HID
== EISA_PNP_ID (0x501)) {
153 if (Acpi
->UID
< 4 && Address
!= MAX_UINT16
&& Irq
!= MAX_UINT8
) {
155 // Get the handle of the child device that has opened the Super I/O Protocol
157 Status
= gBS
->OpenProtocolInformation (
159 &gEfiSioProtocolGuid
,
163 if (EFI_ERROR (Status
)) {
166 for (ChildIndex
= 0; ChildIndex
< EntryCount
; ChildIndex
++) {
167 if ((OpenInfoBuffer
[ChildIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
168 Status
= gBS
->HandleProtocol (OpenInfoBuffer
[ChildIndex
].ControllerHandle
, &gEfiSerialIoProtocolGuid
, (VOID
**) &SerialIo
);
169 if (!EFI_ERROR (Status
)) {
170 SioSerial
= &SioPtr
->Serial
[Acpi
->UID
];
171 SioSerial
->Address
= Address
;
172 SioSerial
->Irq
= Irq
;
173 SioSerial
->Mode
= DEVICE_SERIAL_MODE_NORMAL
| DEVICE_SERIAL_MODE_DUPLEX_HALF
;
179 FreePool (OpenInfoBuffer
);
183 // See if this is an ISA parallel port
185 // Ignore DMA resource since it is always returned NULL, port
186 // only used in output mode.
188 if (Acpi
->HID
== EISA_PNP_ID (0x400) || Acpi
->HID
== EISA_PNP_ID (0x401)) {
189 if (Acpi
->UID
< 3 && Address
!= MAX_UINT16
&& Irq
!= MAX_UINT8
&& Dma
!= MAX_UINT8
) {
190 SioParallel
= &SioPtr
->Parallel
[Acpi
->UID
];
191 SioParallel
->Address
= Address
;
192 SioParallel
->Irq
= Irq
;
193 SioParallel
->Dma
= Dma
;
194 SioParallel
->Mode
= DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY
;
198 // See if this is an ISA floppy controller
200 if (Acpi
->HID
== EISA_PNP_ID (0x604)) {
201 if (Address
!= MAX_UINT16
&& Irq
!= MAX_UINT8
&& Dma
!= MAX_UINT8
) {
202 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiBlockIoProtocolGuid
, (VOID
**) &BlockIo
);
203 if (!EFI_ERROR (Status
)) {
204 SioFloppy
= &SioPtr
->Floppy
;
205 SioFloppy
->Address
= Address
;
206 SioFloppy
->Irq
= Irq
;
207 SioFloppy
->Dma
= Dma
;
208 SioFloppy
->NumberOfFloppy
++;
213 // See if this is a mouse
214 // Always set mouse found so USB hot plug will work
216 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
218 // Hid = ResourceList->Device.HID & 0xff00ffff;
219 // PnpId = EISA_PNP_ID(0x0f00);
220 // if (Hid == PnpId) {
221 // if (ResourceList->Device.UID == 1) {
222 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
223 // if (!EFI_ERROR (Status)) {
225 SioPtr
->MousePresent
= 0x01;
233 FreePool (HandleBuffer
);
239 Collect EFI Info about legacy devices through ISA IO interface.
241 @param SioPtr Pointer to SIO data.
243 @retval EFI_SUCCESS When SIO data is got successfully.
244 @retval EFI_NOT_FOUND When ISA IO interface is absent.
248 LegacyBiosBuildSioDataFromIsaIo (
249 IN DEVICE_PRODUCER_DATA_HEADER
*SioPtr
253 DEVICE_PRODUCER_SERIAL
*SioSerial
;
254 DEVICE_PRODUCER_PARALLEL
*SioParallel
;
255 DEVICE_PRODUCER_FLOPPY
*SioFloppy
;
257 EFI_HANDLE
*HandleBuffer
;
261 EFI_ISA_IO_PROTOCOL
*IsaIo
;
262 EFI_ISA_ACPI_RESOURCE_LIST
*ResourceList
;
263 EFI_ISA_ACPI_RESOURCE
*IoResource
;
264 EFI_ISA_ACPI_RESOURCE
*DmaResource
;
265 EFI_ISA_ACPI_RESOURCE
*InterruptResource
;
267 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
268 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
269 EFI_SERIAL_IO_PROTOCOL
*SerialIo
;
272 // Get the list of ISA controllers in the system
274 Status
= gBS
->LocateHandleBuffer (
276 &gEfiIsaIoProtocolGuid
,
281 if (EFI_ERROR (Status
)) {
282 return EFI_NOT_FOUND
;
285 // Collect legacy information from each of the ISA controllers in the system
287 for (Index
= 0; Index
< HandleCount
; Index
++) {
289 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiIsaIoProtocolGuid
, (VOID
**) &IsaIo
);
290 if (EFI_ERROR (Status
)) {
294 ResourceList
= IsaIo
->ResourceList
;
296 if (ResourceList
== NULL
) {
300 // Collect the resource types neededto fill in the SIO data structure
304 InterruptResource
= NULL
;
305 for (ResourceIndex
= 0;
306 ResourceList
->ResourceItem
[ResourceIndex
].Type
!= EfiIsaAcpiResourceEndOfList
;
309 switch (ResourceList
->ResourceItem
[ResourceIndex
].Type
) {
310 case EfiIsaAcpiResourceIo
:
311 IoResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
314 case EfiIsaAcpiResourceMemory
:
317 case EfiIsaAcpiResourceDma
:
318 DmaResource
= &ResourceList
->ResourceItem
[ResourceIndex
];
321 case EfiIsaAcpiResourceInterrupt
:
322 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)) {
336 if (ResourceList
->Device
.UID
<= 3 &&
337 IoResource
!= NULL
&&
338 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
)) {
353 // We want resource for legacy even if no 32-bit driver installed
355 for (ChildIndex
= 0; ChildIndex
< EntryCount
; ChildIndex
++) {
356 if ((OpenInfoBuffer
[ChildIndex
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
357 Status
= gBS
->HandleProtocol (OpenInfoBuffer
[ChildIndex
].ControllerHandle
, &gEfiSerialIoProtocolGuid
, (VOID
**) &SerialIo
);
358 if (!EFI_ERROR (Status
)) {
359 SioSerial
= &SioPtr
->Serial
[ResourceList
->Device
.UID
];
360 SioSerial
->Address
= (UINT16
) IoResource
->StartRange
;
361 SioSerial
->Irq
= (UINT8
) InterruptResource
->StartRange
;
362 SioSerial
->Mode
= DEVICE_SERIAL_MODE_NORMAL
| DEVICE_SERIAL_MODE_DUPLEX_HALF
;
368 FreePool (OpenInfoBuffer
);
372 // See if this is an ISA parallel port
374 // Ignore DMA resource since it is always returned NULL, port
375 // only used in output mode.
377 if (ResourceList
->Device
.HID
== EISA_PNP_ID (0x400) || ResourceList
->Device
.HID
== EISA_PNP_ID (0x401)) {
378 if (ResourceList
->Device
.UID
<= 2 &&
379 IoResource
!= NULL
&&
380 InterruptResource
!= NULL
&&
383 SioParallel
= &SioPtr
->Parallel
[ResourceList
->Device
.UID
];
384 SioParallel
->Address
= (UINT16
) IoResource
->StartRange
;
385 SioParallel
->Irq
= (UINT8
) InterruptResource
->StartRange
;
386 SioParallel
->Dma
= (UINT8
) DmaResource
->StartRange
;
387 SioParallel
->Mode
= DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY
;
391 // See if this is an ISA floppy controller
393 if (ResourceList
->Device
.HID
== EISA_PNP_ID (0x604)) {
394 if (IoResource
!= NULL
&& InterruptResource
!= NULL
&& DmaResource
!= NULL
) {
395 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiBlockIoProtocolGuid
, (VOID
**) &BlockIo
);
396 if (!EFI_ERROR (Status
)) {
397 SioFloppy
= &SioPtr
->Floppy
;
398 SioFloppy
->Address
= (UINT16
) IoResource
->StartRange
;
399 SioFloppy
->Irq
= (UINT8
) InterruptResource
->StartRange
;
400 SioFloppy
->Dma
= (UINT8
) DmaResource
->StartRange
;
401 SioFloppy
->NumberOfFloppy
++;
406 // See if this is a mouse
407 // Always set mouse found so USB hot plug will work
409 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.
411 // Hid = ResourceList->Device.HID & 0xff00ffff;
412 // PnpId = EISA_PNP_ID(0x0f00);
413 // if (Hid == PnpId) {
414 // if (ResourceList->Device.UID == 1) {
415 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);
416 // if (!EFI_ERROR (Status)) {
418 SioPtr
->MousePresent
= 0x01;
426 FreePool (HandleBuffer
);
431 Collect EFI Info about legacy devices.
433 @param Private Legacy BIOS Instance data
435 @retval EFI_SUCCESS It should always work.
439 LegacyBiosBuildSioData (
440 IN LEGACY_BIOS_INSTANCE
*Private
444 DEVICE_PRODUCER_DATA_HEADER
*SioPtr
;
445 EFI_HANDLE IsaBusController
;
447 EFI_HANDLE
*HandleBuffer
;
450 // Get the pointer to the SIO data structure
452 SioPtr
= &Private
->IntThunk
->EfiToLegacy16BootTable
.SioData
;
455 // Zero the data in the SIO data structure
457 gBS
->SetMem (SioPtr
, sizeof (DEVICE_PRODUCER_DATA_HEADER
), 0);
460 // Find the ISA Bus Controller used for legacy
462 Status
= Private
->LegacyBiosPlatform
->GetPlatformHandle (
463 Private
->LegacyBiosPlatform
,
464 EfiGetPlatformIsaBusHandle
,
470 IsaBusController
= HandleBuffer
[0];
471 if (!EFI_ERROR (Status
)) {
473 // Force ISA Bus Controller to produce all ISA devices
475 gBS
->ConnectController (IsaBusController
, NULL
, NULL
, TRUE
);
478 Status
= LegacyBiosBuildSioDataFromIsaIo (SioPtr
);
479 if (EFI_ERROR (Status
)) {
480 LegacyBiosBuildSioDataFromSio (SioPtr
);