]> git.proxmox.com Git - mirror_edk2.git/blame - UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c
UefiPayloadPkg/BootManager: Add PS2 keyboard support
[mirror_edk2.git] / UefiPayloadPkg / Library / PlatformBootManagerLib / PlatformConsole.c
CommitLineData
04af8bf2
DG
1/** @file\r
2This file include all platform action which can be customized by IBV/OEM.\r
3\r
4Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
5SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "PlatformBootManager.h"\r
10#include "PlatformConsole.h"\r
fec63bb9 11#include <Guid/SerialPortLibVendor.h>\r
04af8bf2
DG
12\r
13#define PCI_DEVICE_PATH_NODE(Func, Dev) \\r
14 { \\r
15 { \\r
16 HARDWARE_DEVICE_PATH, \\r
17 HW_PCI_DP, \\r
18 { \\r
19 (UINT8) (sizeof (PCI_DEVICE_PATH)), \\r
20 (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \\r
21 } \\r
22 }, \\r
23 (Func), \\r
24 (Dev) \\r
25 }\r
26\r
27#define PNPID_DEVICE_PATH_NODE(PnpId) \\r
28 { \\r
29 { \\r
30 ACPI_DEVICE_PATH, \\r
31 ACPI_DP, \\r
32 { \\r
33 (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \\r
34 (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \\r
35 }, \\r
36 }, \\r
37 EISA_PNP_ID((PnpId)), \\r
38 0 \\r
39 }\r
40\r
41#define gPciRootBridge \\r
42 PNPID_DEVICE_PATH_NODE(0x0A03)\r
43\r
44#define gPnp16550ComPort \\r
45 PNPID_DEVICE_PATH_NODE(0x0501)\r
46\r
33a32936
DG
47#define gPnpPs2Keyboard \\r
48 PNPID_DEVICE_PATH_NODE(0x0303)\r
49\r
04af8bf2
DG
50#define gUartVendor \\r
51 { \\r
52 { \\r
53 HARDWARE_DEVICE_PATH, \\r
54 HW_VENDOR_DP, \\r
55 { \\r
56 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \\r
57 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \\r
58 } \\r
59 }, \\r
fec63bb9 60 EDKII_SERIAL_PORT_LIB_VENDOR_GUID \\r
04af8bf2
DG
61 }\r
62\r
63#define gUart \\r
64 { \\r
65 { \\r
66 MESSAGING_DEVICE_PATH, \\r
67 MSG_UART_DP, \\r
68 { \\r
69 (UINT8) (sizeof (UART_DEVICE_PATH)), \\r
70 (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \\r
71 } \\r
72 }, \\r
73 0, \\r
74 115200, \\r
75 8, \\r
76 1, \\r
77 1 \\r
78 }\r
79\r
80#define gPcAnsiTerminal \\r
81 { \\r
82 { \\r
83 MESSAGING_DEVICE_PATH, \\r
84 MSG_VENDOR_DP, \\r
85 { \\r
86 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \\r
87 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \\r
88 } \\r
89 }, \\r
90 DEVICE_PATH_MESSAGING_PC_ANSI \\r
91 }\r
92\r
33a32936 93ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;\r
04af8bf2
DG
94ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;\r
95UART_DEVICE_PATH gUartDeviceNode = gUart;\r
96VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;\r
97VENDOR_DEVICE_PATH gUartDeviceVendorNode = gUartVendor;\r
98\r
99//\r
100// Predefined platform root bridge\r
101//\r
102PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {\r
103 gPciRootBridge,\r
104 gEndEntire\r
105};\r
106\r
107EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = {\r
108 (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,\r
109 NULL\r
110};\r
111\r
112BOOLEAN mDetectVgaOnly;\r
113\r
114/**\r
33a32936 115 Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.\r
04af8bf2 116\r
33a32936 117 @param[in] DeviceHandle Handle of the LPC Bridge device.\r
04af8bf2 118\r
33a32936
DG
119 @retval EFI_SUCCESS Console devices on the LPC bridge have been added to\r
120 ConOut, ConIn, and ErrOut.\r
121\r
122 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing\r
123 from DeviceHandle.\r
04af8bf2
DG
124**/\r
125EFI_STATUS\r
126PrepareLpcBridgeDevicePath (\r
127 IN EFI_HANDLE DeviceHandle\r
128)\r
129{\r
130 EFI_STATUS Status;\r
131 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
33a32936 132 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
04af8bf2
DG
133\r
134 DevicePath = NULL;\r
135 Status = gBS->HandleProtocol (\r
136 DeviceHandle,\r
137 &gEfiDevicePathProtocolGuid,\r
138 (VOID*)&DevicePath\r
139 );\r
140 if (EFI_ERROR (Status)) {\r
141 return Status;\r
142 }\r
33a32936
DG
143 TempDevicePath = DevicePath;\r
144\r
145 //\r
146 // Register Keyboard\r
147 //\r
148 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
149 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
04af8bf2
DG
150\r
151 //\r
152 // Register COM1\r
153 //\r
33a32936 154 DevicePath = TempDevicePath;\r
04af8bf2
DG
155 DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)NULL, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceVendorNode);\r
156 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
157 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
158\r
159 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
160 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
161 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166/**\r
167 Return the GOP device path in the platform.\r
168\r
169 @param[in] PciDevicePath - Device path for the PCI graphics device.\r
170 @param[out] GopDevicePath - Return the device path with GOP installed.\r
171\r
172 @retval EFI_SUCCESS - PCI VGA is added to ConOut.\r
173 @retval EFI_INVALID_PARAMETER - The device path parameter is invalid.\r
174 @retval EFI_STATUS - No GOP device found.\r
175**/\r
176EFI_STATUS\r
177GetGopDevicePath (\r
178 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
179 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
180)\r
181{\r
182 UINTN Index;\r
183 EFI_STATUS Status;\r
184 EFI_HANDLE PciDeviceHandle;\r
185 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
186 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
187 UINTN GopHandleCount;\r
188 EFI_HANDLE *GopHandleBuffer;\r
189\r
190 if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
191 return EFI_INVALID_PARAMETER;\r
192 }\r
193\r
194 //\r
195 // Initialize the GopDevicePath to be PciDevicePath\r
196 //\r
197 *GopDevicePath = PciDevicePath;\r
198 TempPciDevicePath = PciDevicePath;\r
199\r
200 Status = gBS->LocateDevicePath (\r
201 &gEfiDevicePathProtocolGuid,\r
202 &TempPciDevicePath,\r
203 &PciDeviceHandle\r
204 );\r
205 if (EFI_ERROR (Status)) {\r
206 return Status;\r
207 }\r
208\r
209 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
210\r
211 Status = gBS->LocateHandleBuffer (\r
212 ByProtocol,\r
213 &gEfiGraphicsOutputProtocolGuid,\r
214 NULL,\r
215 &GopHandleCount,\r
216 &GopHandleBuffer\r
217 );\r
218 if (!EFI_ERROR (Status)) {\r
219 //\r
220 // Add all the child handles as possible Console Device\r
221 //\r
222 for (Index = 0; Index < GopHandleCount; Index++) {\r
223 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
224 if (EFI_ERROR (Status)) {\r
225 continue;\r
226 }\r
227 if (CompareMem (\r
228 PciDevicePath,\r
229 TempDevicePath,\r
230 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
231 ) == 0) {\r
232 //\r
233 // In current implementation, we only enable one of the child handles\r
234 // as console device, i.e. sotre one of the child handle's device\r
235 // path to variable "ConOut"\r
236 // In future, we could select all child handles to be console device\r
237 //\r
238 *GopDevicePath = TempDevicePath;\r
239\r
240 //\r
241 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
242 // Add the integrity GOP device path.\r
243 //\r
244 EfiBootManagerUpdateConsoleVariable (ConOut, NULL, PciDevicePath);\r
245 EfiBootManagerUpdateConsoleVariable (ConOut, TempDevicePath, NULL);\r
246 }\r
247 }\r
248 gBS->FreePool (GopHandleBuffer);\r
249 }\r
250\r
251 return EFI_SUCCESS;\r
252}\r
253\r
254/**\r
255 Add PCI VGA to ConOut, ConIn, ErrOut.\r
256\r
257 @param[in] DeviceHandle - Handle of PciIo protocol.\r
258\r
259 @retval EFI_SUCCESS - PCI VGA is added to ConOut.\r
260 @retval EFI_STATUS - No PCI VGA device is added.\r
261\r
262**/\r
263EFI_STATUS\r
264PreparePciVgaDevicePath (\r
265 IN EFI_HANDLE DeviceHandle\r
266)\r
267{\r
268 EFI_STATUS Status;\r
269 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
270 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
271\r
272 DevicePath = NULL;\r
273 Status = gBS->HandleProtocol (\r
274 DeviceHandle,\r
275 &gEfiDevicePathProtocolGuid,\r
276 (VOID*)&DevicePath\r
277 );\r
278 if (EFI_ERROR (Status)) {\r
279 return Status;\r
280 }\r
281\r
282 GetGopDevicePath (DevicePath, &GopDevicePath);\r
283 DevicePath = GopDevicePath;\r
284\r
285 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
286\r
287 return EFI_SUCCESS;\r
288}\r
289\r
290/**\r
291 Add PCI Serial to ConOut, ConIn, ErrOut.\r
292\r
293 @param[in] DeviceHandle - Handle of PciIo protocol.\r
294\r
295 @retval EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.\r
296 @retval EFI_STATUS - No PCI Serial device is added.\r
297\r
298**/\r
299EFI_STATUS\r
300PreparePciSerialDevicePath (\r
301 IN EFI_HANDLE DeviceHandle\r
302)\r
303{\r
304 EFI_STATUS Status;\r
305 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
306\r
307 DevicePath = NULL;\r
308 Status = gBS->HandleProtocol (\r
309 DeviceHandle,\r
310 &gEfiDevicePathProtocolGuid,\r
311 (VOID*)&DevicePath\r
312 );\r
313 if (EFI_ERROR (Status)) {\r
314 return Status;\r
315 }\r
316\r
317 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
318 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
319\r
320 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
321 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
322 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
323\r
324 return EFI_SUCCESS;\r
325}\r
326\r
327\r
328/**\r
329 For every PCI instance execute a callback function.\r
330\r
331 @param[in] Id - The protocol GUID for callback\r
332 @param[in] CallBackFunction - The callback function\r
333 @param[in] Context - The context of the callback\r
334\r
335 @retval EFI_STATUS - Callback function failed.\r
336\r
337**/\r
338EFI_STATUS\r
339EFIAPI\r
340VisitAllInstancesOfProtocol (\r
341 IN EFI_GUID *Id,\r
342 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
343 IN VOID *Context\r
344)\r
345{\r
346 EFI_STATUS Status;\r
347 UINTN HandleCount;\r
348 EFI_HANDLE *HandleBuffer;\r
349 UINTN Index;\r
350 VOID *Instance;\r
351\r
352 //\r
353 // Start to check all the PciIo to find all possible device\r
354 //\r
355 HandleCount = 0;\r
356 HandleBuffer = NULL;\r
357 Status = gBS->LocateHandleBuffer (\r
358 ByProtocol,\r
359 Id,\r
360 NULL,\r
361 &HandleCount,\r
362 &HandleBuffer\r
363 );\r
364 if (EFI_ERROR (Status)) {\r
365 return Status;\r
366 }\r
367\r
368 for (Index = 0; Index < HandleCount; Index++) {\r
369 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
370 if (EFI_ERROR (Status)) {\r
371 continue;\r
372 }\r
373\r
374 Status = (*CallBackFunction) (\r
375 HandleBuffer[Index],\r
376 Instance,\r
377 Context\r
378 );\r
379 }\r
380\r
381 gBS->FreePool (HandleBuffer);\r
382\r
383 return EFI_SUCCESS;\r
384}\r
385\r
386\r
387/**\r
388 For every PCI instance execute a callback function.\r
389\r
390 @param[in] Handle - The PCI device handle\r
391 @param[in] Instance - The instance of the PciIo protocol\r
392 @param[in] Context - The context of the callback\r
393\r
394 @retval EFI_STATUS - Callback function failed.\r
395\r
396**/\r
397EFI_STATUS\r
398EFIAPI\r
399VisitingAPciInstance (\r
400 IN EFI_HANDLE Handle,\r
401 IN VOID *Instance,\r
402 IN VOID *Context\r
403)\r
404{\r
405 EFI_STATUS Status;\r
406 EFI_PCI_IO_PROTOCOL *PciIo;\r
407 PCI_TYPE00 Pci;\r
408\r
409 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;\r
410\r
411 //\r
412 // Check for all PCI device\r
413 //\r
414 Status = PciIo->Pci.Read (\r
415 PciIo,\r
416 EfiPciIoWidthUint32,\r
417 0,\r
418 sizeof (Pci) / sizeof (UINT32),\r
419 &Pci\r
420 );\r
421 if (EFI_ERROR (Status)) {\r
422 return Status;\r
423 }\r
424\r
425 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (\r
426 Handle,\r
427 PciIo,\r
428 &Pci\r
429 );\r
430\r
431}\r
432\r
433\r
434/**\r
435 For every PCI instance execute a callback function.\r
436\r
437 @param[in] CallBackFunction - Callback function pointer\r
438\r
439 @retval EFI_STATUS - Callback function failed.\r
440\r
441**/\r
442EFI_STATUS\r
443EFIAPI\r
444VisitAllPciInstances (\r
445 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
446)\r
447{\r
448 return VisitAllInstancesOfProtocol (\r
449 &gEfiPciIoProtocolGuid,\r
450 VisitingAPciInstance,\r
451 (VOID*)(UINTN) CallBackFunction\r
452 );\r
453}\r
454\r
455\r
456/**\r
457 Do platform specific PCI Device check and add them to\r
458 ConOut, ConIn, ErrOut.\r
459\r
460 @param[in] Handle - Handle of PCI device instance\r
461 @param[in] PciIo - PCI IO protocol instance\r
462 @param[in] Pci - PCI Header register block\r
463\r
464 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
465 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
466\r
467**/\r
468EFI_STATUS\r
469EFIAPI\r
470DetectAndPreparePlatformPciDevicePath (\r
471 IN EFI_HANDLE Handle,\r
472 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
473 IN PCI_TYPE00 *Pci\r
474)\r
475{\r
476 EFI_STATUS Status;\r
477\r
478 Status = PciIo->Attributes (\r
479 PciIo,\r
480 EfiPciIoAttributeOperationEnable,\r
481 EFI_PCI_DEVICE_ENABLE,\r
482 NULL\r
483 );\r
484 ASSERT_EFI_ERROR (Status);\r
485\r
486 if (!mDetectVgaOnly) {\r
487 //\r
488 // Here we decide whether it is LPC Bridge\r
489 //\r
490 if ((IS_PCI_LPC (Pci)) ||\r
491 ((IS_PCI_ISA_PDECODE (Pci)) &&\r
492 (Pci->Hdr.VendorId == 0x8086)\r
493 )\r
494 ) {\r
495 //\r
496 // Add IsaKeyboard to ConIn,\r
497 // add IsaSerial to ConOut, ConIn, ErrOut\r
498 //\r
499 DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));\r
500 PrepareLpcBridgeDevicePath (Handle);\r
501 return EFI_SUCCESS;\r
502 }\r
503 //\r
504 // Here we decide which Serial device to enable in PCI bus\r
505 //\r
506 if (IS_PCI_16550SERIAL (Pci)) {\r
507 //\r
508 // Add them to ConOut, ConIn, ErrOut.\r
509 //\r
510 DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));\r
511 PreparePciSerialDevicePath (Handle);\r
512 return EFI_SUCCESS;\r
513 }\r
514 }\r
515\r
516 //\r
517 // Here we decide which VGA device to enable in PCI bus\r
518 //\r
519 if (IS_PCI_VGA (Pci)) {\r
520 //\r
521 // Add them to ConOut.\r
522 //\r
523 DEBUG ((DEBUG_INFO, "Found PCI VGA device\n"));\r
524 PreparePciVgaDevicePath (Handle);\r
525 return EFI_SUCCESS;\r
526 }\r
527\r
528 return Status;\r
529}\r
530\r
531\r
532/**\r
533 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
534\r
535 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.\r
536\r
537 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
538 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
539\r
540**/\r
541EFI_STATUS\r
542DetectAndPreparePlatformPciDevicePaths (\r
543 BOOLEAN DetectVgaOnly\r
544)\r
545{\r
546 mDetectVgaOnly = DetectVgaOnly;\r
547\r
548 EfiBootManagerUpdateConsoleVariable (\r
549 ConIn,\r
550 (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath,\r
551 NULL\r
552 );\r
553\r
554 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
555}\r
556\r
557\r
558/**\r
559 The function will connect root bridge\r
560\r
561 @return EFI_SUCCESS Connect RootBridge successfully.\r
562\r
563**/\r
564EFI_STATUS\r
565ConnectRootBridge (\r
566 VOID\r
567)\r
568{\r
569 EFI_STATUS Status;\r
570 EFI_HANDLE RootHandle;\r
571\r
572 //\r
573 // Make all the PCI_IO protocols on PCI Seg 0 show up\r
574 //\r
575 Status = gBS->LocateDevicePath (\r
576 &gEfiDevicePathProtocolGuid,\r
577 &gPlatformRootBridges[0],\r
578 &RootHandle\r
579 );\r
580 if (EFI_ERROR (Status)) {\r
581 return Status;\r
582 }\r
583\r
584 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);\r
585 if (EFI_ERROR (Status)) {\r
586 return Status;\r
587 }\r
588\r
589 return EFI_SUCCESS;\r
590}\r
591\r
592/**\r
593 Platform console init. Include the platform firmware vendor, revision\r
594 and so crc check.\r
595\r
596**/\r
597VOID\r
598EFIAPI\r
599PlatformConsoleInit (\r
600 VOID\r
601)\r
602{\r
603 gUartDeviceNode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
604 gUartDeviceNode.DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
605 gUartDeviceNode.Parity = PcdGet8 (PcdUartDefaultParity);\r
606 gUartDeviceNode.StopBits = PcdGet8 (PcdUartDefaultStopBits);\r
607\r
608 ConnectRootBridge ();\r
609\r
610 //\r
611 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
612 //\r
613 DetectAndPreparePlatformPciDevicePaths (FALSE);\r
614\r
615}\r