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