]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Csm/LegacyBiosDxe/LegacySio.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Csm / LegacyBiosDxe / LegacySio.c
CommitLineData
b522c77b
HW
1/** @file\r
2 Collect Sio information from Native EFI Drivers.\r
3 Sio is floppy, parallel, serial, ... hardware\r
4\r
5Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
6\r
7SPDX-License-Identifier: BSD-2-Clause-Patent\r
8\r
9**/\r
10\r
11#include "LegacyBiosInterface.h"\r
12\r
13/**\r
14 Collect EFI Info about legacy devices through Super IO interface.\r
15\r
16 @param SioPtr Pointer to SIO data.\r
17\r
18 @retval EFI_SUCCESS When SIO data is got successfully.\r
19 @retval EFI_NOT_FOUND When ISA IO interface is absent.\r
20\r
21**/\r
22EFI_STATUS\r
23LegacyBiosBuildSioDataFromSio (\r
ac0a286f 24 IN DEVICE_PRODUCER_DATA_HEADER *SioPtr\r
b522c77b
HW
25 )\r
26{\r
ac0a286f
MK
27 EFI_STATUS Status;\r
28 DEVICE_PRODUCER_SERIAL *SioSerial;\r
29 DEVICE_PRODUCER_PARALLEL *SioParallel;\r
30 DEVICE_PRODUCER_FLOPPY *SioFloppy;\r
31 UINTN HandleCount;\r
32 EFI_HANDLE *HandleBuffer;\r
33 UINTN Index;\r
34 UINTN ChildIndex;\r
35 EFI_SIO_PROTOCOL *Sio;\r
36 ACPI_RESOURCE_HEADER_PTR Resources;\r
37 EFI_ACPI_IO_PORT_DESCRIPTOR *IoResource;\r
38 EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *FixedIoResource;\r
39 EFI_ACPI_DMA_DESCRIPTOR *DmaResource;\r
40 EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR *IrqResource;\r
41 UINT16 Address;\r
42 UINT8 Dma;\r
43 UINT8 Irq;\r
44 UINTN EntryCount;\r
45 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
46 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
47 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
48 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
49 ACPI_HID_DEVICE_PATH *Acpi;\r
b522c77b
HW
50\r
51 //\r
52 // Get the list of ISA controllers in the system\r
53 //\r
54 Status = gBS->LocateHandleBuffer (\r
55 ByProtocol,\r
56 &gEfiSioProtocolGuid,\r
57 NULL,\r
58 &HandleCount,\r
59 &HandleBuffer\r
60 );\r
61 if (EFI_ERROR (Status)) {\r
62 return EFI_NOT_FOUND;\r
63 }\r
ac0a286f 64\r
b522c77b
HW
65 //\r
66 // Collect legacy information from each of the ISA controllers in the system\r
67 //\r
68 for (Index = 0; Index < HandleCount; Index++) {\r
ac0a286f 69 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSioProtocolGuid, (VOID **)&Sio);\r
b522c77b
HW
70 if (EFI_ERROR (Status)) {\r
71 continue;\r
72 }\r
73\r
74 Address = MAX_UINT16;\r
75 Dma = MAX_UINT8;\r
76 Irq = MAX_UINT8;\r
ac0a286f 77 Status = Sio->GetResources (Sio, &Resources);\r
b522c77b
HW
78 if (!EFI_ERROR (Status)) {\r
79 //\r
80 // Get the base address information from ACPI resource descriptor.\r
81 //\r
82 while (Resources.SmallHeader->Byte != ACPI_END_TAG_DESCRIPTOR) {\r
83 switch (Resources.SmallHeader->Byte) {\r
ac0a286f
MK
84 case ACPI_IO_PORT_DESCRIPTOR:\r
85 IoResource = (EFI_ACPI_IO_PORT_DESCRIPTOR *)Resources.SmallHeader;\r
86 Address = IoResource->BaseAddressMin;\r
87 break;\r
88\r
89 case ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR:\r
90 FixedIoResource = (EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR *)Resources.SmallHeader;\r
91 Address = FixedIoResource->BaseAddress;\r
92 break;\r
93\r
94 case ACPI_DMA_DESCRIPTOR:\r
95 DmaResource = (EFI_ACPI_DMA_DESCRIPTOR *)Resources.SmallHeader;\r
96 Dma = (UINT8)LowBitSet32 (DmaResource->ChannelMask);\r
97 break;\r
98\r
99 case ACPI_IRQ_DESCRIPTOR:\r
100 case ACPI_IRQ_NOFLAG_DESCRIPTOR:\r
101 IrqResource = (EFI_ACPI_IRQ_NOFLAG_DESCRIPTOR *)Resources.SmallHeader;\r
102 Irq = (UINT8)LowBitSet32 (IrqResource->Mask);\r
103 break;\r
104\r
105 default:\r
106 break;\r
b522c77b
HW
107 }\r
108\r
109 if (Resources.SmallHeader->Bits.Type == 0) {\r
ac0a286f
MK
110 Resources.SmallHeader = (ACPI_SMALL_RESOURCE_HEADER *)((UINT8 *)Resources.SmallHeader\r
111 + Resources.SmallHeader->Bits.Length\r
112 + sizeof (*Resources.SmallHeader));\r
b522c77b 113 } else {\r
ac0a286f
MK
114 Resources.LargeHeader = (ACPI_LARGE_RESOURCE_HEADER *)((UINT8 *)Resources.LargeHeader\r
115 + Resources.LargeHeader->Length\r
116 + sizeof (*Resources.LargeHeader));\r
b522c77b
HW
117 }\r
118 }\r
119 }\r
120\r
70d5086c 121 DEBUG ((DEBUG_INFO, "LegacySio: Address/Dma/Irq = %x/%d/%d\n", Address, Dma, Irq));\r
b522c77b
HW
122\r
123 DevicePath = DevicePathFromHandle (HandleBuffer[Index]);\r
124 if (DevicePath == NULL) {\r
125 continue;\r
126 }\r
127\r
128 Acpi = NULL;\r
129 while (!IsDevicePathEnd (DevicePath)) {\r
ac0a286f 130 Acpi = (ACPI_HID_DEVICE_PATH *)DevicePath;\r
b522c77b
HW
131 DevicePath = NextDevicePathNode (DevicePath);\r
132 }\r
133\r
134 if ((Acpi == NULL) || (DevicePathType (Acpi) != ACPI_DEVICE_PATH) ||\r
135 ((DevicePathSubType (Acpi) != ACPI_DP) && (DevicePathSubType (Acpi) != ACPI_EXTENDED_DP))\r
ac0a286f
MK
136 )\r
137 {\r
b522c77b
HW
138 continue;\r
139 }\r
140\r
141 //\r
142 // See if this is an ISA serial port\r
143 //\r
144 // Ignore DMA resource since it is always returned NULL\r
145 //\r
ac0a286f
MK
146 if ((Acpi->HID == EISA_PNP_ID (0x500)) || (Acpi->HID == EISA_PNP_ID (0x501))) {\r
147 if ((Acpi->UID < 4) && (Address != MAX_UINT16) && (Irq != MAX_UINT8)) {\r
b522c77b
HW
148 //\r
149 // Get the handle of the child device that has opened the Super I/O Protocol\r
150 //\r
151 Status = gBS->OpenProtocolInformation (\r
152 HandleBuffer[Index],\r
153 &gEfiSioProtocolGuid,\r
154 &OpenInfoBuffer,\r
155 &EntryCount\r
156 );\r
157 if (EFI_ERROR (Status)) {\r
158 continue;\r
159 }\r
ac0a286f 160\r
b522c77b
HW
161 for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {\r
162 if ((OpenInfoBuffer[ChildIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
ac0a286f 163 Status = gBS->HandleProtocol (OpenInfoBuffer[ChildIndex].ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **)&SerialIo);\r
b522c77b 164 if (!EFI_ERROR (Status)) {\r
ac0a286f
MK
165 SioSerial = &SioPtr->Serial[Acpi->UID];\r
166 SioSerial->Address = Address;\r
167 SioSerial->Irq = Irq;\r
168 SioSerial->Mode = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;\r
b522c77b
HW
169 break;\r
170 }\r
171 }\r
172 }\r
173\r
174 FreePool (OpenInfoBuffer);\r
175 }\r
176 }\r
ac0a286f 177\r
b522c77b
HW
178 //\r
179 // See if this is an ISA parallel port\r
180 //\r
181 // Ignore DMA resource since it is always returned NULL, port\r
182 // only used in output mode.\r
183 //\r
ac0a286f
MK
184 if ((Acpi->HID == EISA_PNP_ID (0x400)) || (Acpi->HID == EISA_PNP_ID (0x401))) {\r
185 if ((Acpi->UID < 3) && (Address != MAX_UINT16) && (Irq != MAX_UINT8) && (Dma != MAX_UINT8)) {\r
186 SioParallel = &SioPtr->Parallel[Acpi->UID];\r
187 SioParallel->Address = Address;\r
188 SioParallel->Irq = Irq;\r
189 SioParallel->Dma = Dma;\r
190 SioParallel->Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;\r
b522c77b
HW
191 }\r
192 }\r
ac0a286f 193\r
b522c77b
HW
194 //\r
195 // See if this is an ISA floppy controller\r
196 //\r
197 if (Acpi->HID == EISA_PNP_ID (0x604)) {\r
ac0a286f
MK
198 if ((Address != MAX_UINT16) && (Irq != MAX_UINT8) && (Dma != MAX_UINT8)) {\r
199 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
b522c77b 200 if (!EFI_ERROR (Status)) {\r
ac0a286f
MK
201 SioFloppy = &SioPtr->Floppy;\r
202 SioFloppy->Address = Address;\r
203 SioFloppy->Irq = Irq;\r
204 SioFloppy->Dma = Dma;\r
b522c77b
HW
205 SioFloppy->NumberOfFloppy++;\r
206 }\r
207 }\r
208 }\r
ac0a286f 209\r
b522c77b
HW
210 //\r
211 // See if this is a mouse\r
212 // Always set mouse found so USB hot plug will work\r
213 //\r
214 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.\r
215 //\r
216 // Hid = ResourceList->Device.HID & 0xff00ffff;\r
217 // PnpId = EISA_PNP_ID(0x0f00);\r
218 // if (Hid == PnpId) {\r
219 // if (ResourceList->Device.UID == 1) {\r
220 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);\r
221 // if (!EFI_ERROR (Status)) {\r
222 //\r
223 SioPtr->MousePresent = 0x01;\r
224 //\r
225 // }\r
226 // }\r
227 // }\r
228 //\r
229 }\r
230\r
231 FreePool (HandleBuffer);\r
232 return EFI_SUCCESS;\r
b522c77b
HW
233}\r
234\r
235/**\r
236 Collect EFI Info about legacy devices through ISA IO interface.\r
237\r
238 @param SioPtr Pointer to SIO data.\r
239\r
240 @retval EFI_SUCCESS When SIO data is got successfully.\r
241 @retval EFI_NOT_FOUND When ISA IO interface is absent.\r
242\r
243**/\r
244EFI_STATUS\r
245LegacyBiosBuildSioDataFromIsaIo (\r
ac0a286f 246 IN DEVICE_PRODUCER_DATA_HEADER *SioPtr\r
b522c77b
HW
247 )\r
248{\r
ac0a286f
MK
249 EFI_STATUS Status;\r
250 DEVICE_PRODUCER_SERIAL *SioSerial;\r
251 DEVICE_PRODUCER_PARALLEL *SioParallel;\r
252 DEVICE_PRODUCER_FLOPPY *SioFloppy;\r
253 UINTN HandleCount;\r
254 EFI_HANDLE *HandleBuffer;\r
255 UINTN Index;\r
256 UINTN ResourceIndex;\r
257 UINTN ChildIndex;\r
258 EFI_ISA_IO_PROTOCOL *IsaIo;\r
259 EFI_ISA_ACPI_RESOURCE_LIST *ResourceList;\r
260 EFI_ISA_ACPI_RESOURCE *IoResource;\r
261 EFI_ISA_ACPI_RESOURCE *DmaResource;\r
262 EFI_ISA_ACPI_RESOURCE *InterruptResource;\r
263 UINTN EntryCount;\r
264 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;\r
265 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
266 EFI_SERIAL_IO_PROTOCOL *SerialIo;\r
b522c77b
HW
267\r
268 //\r
269 // Get the list of ISA controllers in the system\r
270 //\r
271 Status = gBS->LocateHandleBuffer (\r
272 ByProtocol,\r
273 &gEfiIsaIoProtocolGuid,\r
274 NULL,\r
275 &HandleCount,\r
276 &HandleBuffer\r
277 );\r
278 if (EFI_ERROR (Status)) {\r
279 return EFI_NOT_FOUND;\r
280 }\r
ac0a286f 281\r
b522c77b
HW
282 //\r
283 // Collect legacy information from each of the ISA controllers in the system\r
284 //\r
285 for (Index = 0; Index < HandleCount; Index++) {\r
ac0a286f 286 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiIsaIoProtocolGuid, (VOID **)&IsaIo);\r
b522c77b
HW
287 if (EFI_ERROR (Status)) {\r
288 continue;\r
289 }\r
290\r
291 ResourceList = IsaIo->ResourceList;\r
292\r
293 if (ResourceList == NULL) {\r
294 continue;\r
295 }\r
ac0a286f 296\r
b522c77b
HW
297 //\r
298 // Collect the resource types neededto fill in the SIO data structure\r
299 //\r
300 IoResource = NULL;\r
301 DmaResource = NULL;\r
302 InterruptResource = NULL;\r
303 for (ResourceIndex = 0;\r
304 ResourceList->ResourceItem[ResourceIndex].Type != EfiIsaAcpiResourceEndOfList;\r
305 ResourceIndex++\r
ac0a286f
MK
306 )\r
307 {\r
b522c77b 308 switch (ResourceList->ResourceItem[ResourceIndex].Type) {\r
ac0a286f
MK
309 case EfiIsaAcpiResourceIo:\r
310 IoResource = &ResourceList->ResourceItem[ResourceIndex];\r
311 break;\r
b522c77b 312\r
ac0a286f
MK
313 case EfiIsaAcpiResourceMemory:\r
314 break;\r
b522c77b 315\r
ac0a286f
MK
316 case EfiIsaAcpiResourceDma:\r
317 DmaResource = &ResourceList->ResourceItem[ResourceIndex];\r
318 break;\r
b522c77b 319\r
ac0a286f
MK
320 case EfiIsaAcpiResourceInterrupt:\r
321 InterruptResource = &ResourceList->ResourceItem[ResourceIndex];\r
322 break;\r
b522c77b 323\r
ac0a286f
MK
324 default:\r
325 break;\r
b522c77b
HW
326 }\r
327 }\r
ac0a286f 328\r
b522c77b
HW
329 //\r
330 // See if this is an ISA serial port\r
331 //\r
332 // Ignore DMA resource since it is always returned NULL\r
333 //\r
ac0a286f
MK
334 if ((ResourceList->Device.HID == EISA_PNP_ID (0x500)) || (ResourceList->Device.HID == EISA_PNP_ID (0x501))) {\r
335 if ((ResourceList->Device.UID <= 3) &&\r
336 (IoResource != NULL) &&\r
337 (InterruptResource != NULL)\r
338 )\r
339 {\r
b522c77b
HW
340 //\r
341 // Get the handle of the child device that has opened the ISA I/O Protocol\r
342 //\r
343 Status = gBS->OpenProtocolInformation (\r
344 HandleBuffer[Index],\r
345 &gEfiIsaIoProtocolGuid,\r
346 &OpenInfoBuffer,\r
347 &EntryCount\r
348 );\r
349 if (EFI_ERROR (Status)) {\r
350 continue;\r
351 }\r
ac0a286f 352\r
b522c77b
HW
353 //\r
354 // We want resource for legacy even if no 32-bit driver installed\r
355 //\r
356 for (ChildIndex = 0; ChildIndex < EntryCount; ChildIndex++) {\r
357 if ((OpenInfoBuffer[ChildIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
ac0a286f 358 Status = gBS->HandleProtocol (OpenInfoBuffer[ChildIndex].ControllerHandle, &gEfiSerialIoProtocolGuid, (VOID **)&SerialIo);\r
b522c77b 359 if (!EFI_ERROR (Status)) {\r
ac0a286f
MK
360 SioSerial = &SioPtr->Serial[ResourceList->Device.UID];\r
361 SioSerial->Address = (UINT16)IoResource->StartRange;\r
362 SioSerial->Irq = (UINT8)InterruptResource->StartRange;\r
363 SioSerial->Mode = DEVICE_SERIAL_MODE_NORMAL | DEVICE_SERIAL_MODE_DUPLEX_HALF;\r
b522c77b
HW
364 break;\r
365 }\r
366 }\r
367 }\r
368\r
369 FreePool (OpenInfoBuffer);\r
370 }\r
371 }\r
ac0a286f 372\r
b522c77b
HW
373 //\r
374 // See if this is an ISA parallel port\r
375 //\r
376 // Ignore DMA resource since it is always returned NULL, port\r
377 // only used in output mode.\r
378 //\r
ac0a286f
MK
379 if ((ResourceList->Device.HID == EISA_PNP_ID (0x400)) || (ResourceList->Device.HID == EISA_PNP_ID (0x401))) {\r
380 if ((ResourceList->Device.UID <= 2) &&\r
381 (IoResource != NULL) &&\r
382 (InterruptResource != NULL) &&\r
383 (DmaResource != NULL)\r
384 )\r
385 {\r
386 SioParallel = &SioPtr->Parallel[ResourceList->Device.UID];\r
387 SioParallel->Address = (UINT16)IoResource->StartRange;\r
388 SioParallel->Irq = (UINT8)InterruptResource->StartRange;\r
389 SioParallel->Dma = (UINT8)DmaResource->StartRange;\r
390 SioParallel->Mode = DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY;\r
b522c77b
HW
391 }\r
392 }\r
ac0a286f 393\r
b522c77b
HW
394 //\r
395 // See if this is an ISA floppy controller\r
396 //\r
397 if (ResourceList->Device.HID == EISA_PNP_ID (0x604)) {\r
ac0a286f
MK
398 if ((IoResource != NULL) && (InterruptResource != NULL) && (DmaResource != NULL)) {\r
399 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiBlockIoProtocolGuid, (VOID **)&BlockIo);\r
b522c77b 400 if (!EFI_ERROR (Status)) {\r
ac0a286f
MK
401 SioFloppy = &SioPtr->Floppy;\r
402 SioFloppy->Address = (UINT16)IoResource->StartRange;\r
403 SioFloppy->Irq = (UINT8)InterruptResource->StartRange;\r
404 SioFloppy->Dma = (UINT8)DmaResource->StartRange;\r
b522c77b
HW
405 SioFloppy->NumberOfFloppy++;\r
406 }\r
407 }\r
408 }\r
ac0a286f 409\r
b522c77b
HW
410 //\r
411 // See if this is a mouse\r
412 // Always set mouse found so USB hot plug will work\r
413 //\r
414 // Ignore lower byte of HID. Pnp0fxx is any type of mouse.\r
415 //\r
416 // Hid = ResourceList->Device.HID & 0xff00ffff;\r
417 // PnpId = EISA_PNP_ID(0x0f00);\r
418 // if (Hid == PnpId) {\r
419 // if (ResourceList->Device.UID == 1) {\r
420 // Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimplePointerProtocolGuid, &SimplePointer);\r
421 // if (!EFI_ERROR (Status)) {\r
422 //\r
423 SioPtr->MousePresent = 0x01;\r
424 //\r
425 // }\r
426 // }\r
427 // }\r
428 //\r
429 }\r
430\r
431 FreePool (HandleBuffer);\r
432 return EFI_SUCCESS;\r
433}\r
434\r
435/**\r
436 Collect EFI Info about legacy devices.\r
437\r
438 @param Private Legacy BIOS Instance data\r
439\r
440 @retval EFI_SUCCESS It should always work.\r
441\r
442**/\r
443EFI_STATUS\r
444LegacyBiosBuildSioData (\r
ac0a286f 445 IN LEGACY_BIOS_INSTANCE *Private\r
b522c77b
HW
446 )\r
447{\r
ac0a286f
MK
448 EFI_STATUS Status;\r
449 DEVICE_PRODUCER_DATA_HEADER *SioPtr;\r
450 EFI_HANDLE IsaBusController;\r
451 UINTN HandleCount;\r
452 EFI_HANDLE *HandleBuffer;\r
b522c77b
HW
453\r
454 //\r
455 // Get the pointer to the SIO data structure\r
456 //\r
457 SioPtr = &Private->IntThunk->EfiToLegacy16BootTable.SioData;\r
458\r
459 //\r
460 // Zero the data in the SIO data structure\r
461 //\r
462 gBS->SetMem (SioPtr, sizeof (DEVICE_PRODUCER_DATA_HEADER), 0);\r
463\r
464 //\r
465 // Find the ISA Bus Controller used for legacy\r
466 //\r
467 Status = Private->LegacyBiosPlatform->GetPlatformHandle (\r
468 Private->LegacyBiosPlatform,\r
469 EfiGetPlatformIsaBusHandle,\r
470 0,\r
471 &HandleBuffer,\r
472 &HandleCount,\r
473 NULL\r
474 );\r
475 IsaBusController = HandleBuffer[0];\r
476 if (!EFI_ERROR (Status)) {\r
477 //\r
478 // Force ISA Bus Controller to produce all ISA devices\r
479 //\r
480 gBS->ConnectController (IsaBusController, NULL, NULL, TRUE);\r
481 }\r
482\r
483 Status = LegacyBiosBuildSioDataFromIsaIo (SioPtr);\r
484 if (EFI_ERROR (Status)) {\r
485 LegacyBiosBuildSioDataFromSio (SioPtr);\r
486 }\r
487\r
488 return EFI_SUCCESS;\r
489}\r