]> git.proxmox.com Git - mirror_edk2.git/blame - CorebootPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c
CorebootPayloadPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / CorebootPayloadPkg / Library / PlatformBootManagerLib / PlatformConsole.c
CommitLineData
42a8f2ce
MM
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
d2e8b7e1 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
42a8f2ce
MM
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 ACPI_ADR_DEVICE_PATH AcpiAdr;\r
174 EFI_DEVICE_PATH_PROTOCOL *MyDevicePath;\r
175\r
176 if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
177 return EFI_INVALID_PARAMETER;\r
178 }\r
179\r
180 MyDevicePath = NULL;\r
181\r
182 //\r
183 // Initialize the GopDevicePath to be PciDevicePath\r
184 //\r
185 *GopDevicePath = PciDevicePath;\r
186 TempPciDevicePath = PciDevicePath;\r
187\r
188 Status = gBS->LocateDevicePath (\r
189 &gEfiDevicePathProtocolGuid,\r
190 &TempPciDevicePath,\r
191 &PciDeviceHandle\r
192 );\r
193 if (EFI_ERROR (Status)) {\r
194 return Status;\r
195 }\r
196\r
197 //\r
e7700ced 198 // Try to connect this handle, so that GOP driver could start on this\r
42a8f2ce
MM
199 // device and create child handles with GraphicsOutput Protocol installed\r
200 // on them, then we get device paths of these child handles and select\r
201 // them as possible console device.\r
202 //\r
203 AcpiAdr.Header.Type = ACPI_DEVICE_PATH;\r
204 AcpiAdr.Header.SubType = ACPI_ADR_DP;\r
205 AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, 8, 0);\r
206\r
207 SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH));\r
208\r
209 MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr);\r
210\r
211 gBS->ConnectController (PciDeviceHandle, NULL, MyDevicePath, FALSE);\r
212\r
213 FreePool(MyDevicePath);\r
214\r
215 Status = gBS->LocateHandleBuffer (\r
216 ByProtocol,\r
217 &gEfiGraphicsOutputProtocolGuid,\r
218 NULL,\r
219 &GopHandleCount,\r
220 &GopHandleBuffer\r
221 );\r
222 if (!EFI_ERROR (Status)) {\r
223 //\r
224 // Add all the child handles as possible Console Device\r
225 //\r
226 for (Index = 0; Index < GopHandleCount; Index++) {\r
227 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
228 if (EFI_ERROR (Status)) {\r
229 continue;\r
230 }\r
231 if (CompareMem (\r
232 PciDevicePath,\r
233 TempDevicePath,\r
234 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
235 ) == 0) {\r
236 //\r
237 // In current implementation, we only enable one of the child handles\r
238 // as console device, i.e. sotre one of the child handle's device\r
239 // path to variable "ConOut"\r
e7700ced 240 // In future, we could select all child handles to be console device\r
42a8f2ce
MM
241 //\r
242 *GopDevicePath = TempDevicePath;\r
243\r
244 //\r
245 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
246 // Add the integrity GOP device path.\r
247 //\r
248 EfiBootManagerUpdateConsoleVariable (ConOut, NULL, PciDevicePath);\r
249 EfiBootManagerUpdateConsoleVariable (ConOut, TempDevicePath, NULL);\r
250 }\r
251 }\r
252 gBS->FreePool (GopHandleBuffer);\r
253 }\r
254\r
255 return EFI_SUCCESS;\r
256}\r
257\r
258/**\r
259 Add PCI VGA to ConOut, ConIn, ErrOut.\r
260\r
261 @param[in] DeviceHandle - Handle of PciIo protocol.\r
262\r
263 @retval EFI_SUCCESS - PCI VGA is added to ConOut.\r
264 @retval EFI_STATUS - No PCI VGA device is added.\r
265\r
266**/\r
267EFI_STATUS\r
268PreparePciVgaDevicePath (\r
269 IN EFI_HANDLE DeviceHandle\r
270)\r
271{\r
272 EFI_STATUS Status;\r
273 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
274 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
275\r
276 DevicePath = NULL;\r
277 Status = gBS->HandleProtocol (\r
278 DeviceHandle,\r
279 &gEfiDevicePathProtocolGuid,\r
280 (VOID*)&DevicePath\r
281 );\r
282 if (EFI_ERROR (Status)) {\r
283 return Status;\r
284 }\r
285\r
286 GetGopDevicePath (DevicePath, &GopDevicePath);\r
287 DevicePath = GopDevicePath;\r
288\r
289 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
290\r
291 return EFI_SUCCESS;\r
292}\r
293\r
294/**\r
295 Add PCI Serial to ConOut, ConIn, ErrOut.\r
296\r
297 @param[in] DeviceHandle - Handle of PciIo protocol.\r
298\r
299 @retval EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.\r
300 @retval EFI_STATUS - No PCI Serial device is added.\r
301\r
302**/\r
303EFI_STATUS\r
304PreparePciSerialDevicePath (\r
305 IN EFI_HANDLE DeviceHandle\r
306)\r
307{\r
308 EFI_STATUS Status;\r
309 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
310\r
311 DevicePath = NULL;\r
312 Status = gBS->HandleProtocol (\r
313 DeviceHandle,\r
314 &gEfiDevicePathProtocolGuid,\r
315 (VOID*)&DevicePath\r
316 );\r
317 if (EFI_ERROR (Status)) {\r
318 return Status;\r
319 }\r
320\r
321 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
322 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
323\r
324 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
325 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
326 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
327\r
328 return EFI_SUCCESS;\r
329}\r
330\r
331\r
332/**\r
333 For every PCI instance execute a callback function.\r
334\r
335 @param[in] Id - The protocol GUID for callback\r
336 @param[in] CallBackFunction - The callback function\r
337 @param[in] Context - The context of the callback\r
338\r
339 @retval EFI_STATUS - Callback function failed.\r
340\r
341**/\r
342EFI_STATUS\r
343EFIAPI\r
344VisitAllInstancesOfProtocol (\r
345 IN EFI_GUID *Id,\r
346 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
347 IN VOID *Context\r
348)\r
349{\r
350 EFI_STATUS Status;\r
351 UINTN HandleCount;\r
352 EFI_HANDLE *HandleBuffer;\r
353 UINTN Index;\r
354 VOID *Instance;\r
355\r
356 //\r
357 // Start to check all the PciIo to find all possible device\r
358 //\r
359 HandleCount = 0;\r
360 HandleBuffer = NULL;\r
361 Status = gBS->LocateHandleBuffer (\r
362 ByProtocol,\r
363 Id,\r
364 NULL,\r
365 &HandleCount,\r
366 &HandleBuffer\r
367 );\r
368 if (EFI_ERROR (Status)) {\r
369 return Status;\r
370 }\r
371\r
372 for (Index = 0; Index < HandleCount; Index++) {\r
373 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
374 if (EFI_ERROR (Status)) {\r
375 continue;\r
376 }\r
377\r
378 Status = (*CallBackFunction) (\r
379 HandleBuffer[Index],\r
380 Instance,\r
381 Context\r
382 );\r
383 }\r
384\r
385 gBS->FreePool (HandleBuffer);\r
386\r
387 return EFI_SUCCESS;\r
388}\r
389\r
390\r
391/**\r
392 For every PCI instance execute a callback function.\r
393\r
394 @param[in] Handle - The PCI device handle\r
395 @param[in] Instance - The instance of the PciIo protocol\r
396 @param[in] Context - The context of the callback\r
397\r
398 @retval EFI_STATUS - Callback function failed.\r
399\r
400**/\r
401EFI_STATUS\r
402EFIAPI\r
403VisitingAPciInstance (\r
404 IN EFI_HANDLE Handle,\r
405 IN VOID *Instance,\r
406 IN VOID *Context\r
407)\r
408{\r
409 EFI_STATUS Status;\r
410 EFI_PCI_IO_PROTOCOL *PciIo;\r
411 PCI_TYPE00 Pci;\r
412\r
413 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;\r
414\r
415 //\r
416 // Check for all PCI device\r
417 //\r
418 Status = PciIo->Pci.Read (\r
419 PciIo,\r
420 EfiPciIoWidthUint32,\r
421 0,\r
422 sizeof (Pci) / sizeof (UINT32),\r
423 &Pci\r
424 );\r
425 if (EFI_ERROR (Status)) {\r
426 return Status;\r
427 }\r
428\r
429 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (\r
430 Handle,\r
431 PciIo,\r
432 &Pci\r
433 );\r
434\r
435}\r
436\r
437\r
438/**\r
439 For every PCI instance execute a callback function.\r
440\r
441 @param[in] CallBackFunction - Callback function pointer\r
442\r
443 @retval EFI_STATUS - Callback function failed.\r
444\r
445**/\r
446EFI_STATUS\r
447EFIAPI\r
448VisitAllPciInstances (\r
449 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
450)\r
451{\r
452 return VisitAllInstancesOfProtocol (\r
453 &gEfiPciIoProtocolGuid,\r
454 VisitingAPciInstance,\r
455 (VOID*)(UINTN) CallBackFunction\r
456 );\r
457}\r
458\r
459\r
460/**\r
461 Do platform specific PCI Device check and add them to\r
462 ConOut, ConIn, ErrOut.\r
463\r
464 @param[in] Handle - Handle of PCI device instance\r
465 @param[in] PciIo - PCI IO protocol instance\r
466 @param[in] Pci - PCI Header register block\r
467\r
468 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
469 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
470\r
471**/\r
472EFI_STATUS\r
473EFIAPI\r
474DetectAndPreparePlatformPciDevicePath (\r
475 IN EFI_HANDLE Handle,\r
476 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
477 IN PCI_TYPE00 *Pci\r
478)\r
479{\r
480 EFI_STATUS Status;\r
481\r
482 Status = PciIo->Attributes (\r
483 PciIo,\r
484 EfiPciIoAttributeOperationEnable,\r
485 EFI_PCI_DEVICE_ENABLE,\r
486 NULL\r
487 );\r
488 ASSERT_EFI_ERROR (Status);\r
489\r
490 if (!mDetectVgaOnly) {\r
491 //\r
492 // Here we decide whether it is LPC Bridge\r
493 //\r
494 if ((IS_PCI_LPC (Pci)) ||\r
495 ((IS_PCI_ISA_PDECODE (Pci)) &&\r
496 (Pci->Hdr.VendorId == 0x8086)\r
497 )\r
498 ) {\r
499 //\r
500 // Add IsaKeyboard to ConIn,\r
501 // add IsaSerial to ConOut, ConIn, ErrOut\r
502 //\r
503 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));\r
504 PrepareLpcBridgeDevicePath (Handle);\r
505 return EFI_SUCCESS;\r
506 }\r
507 //\r
508 // Here we decide which Serial device to enable in PCI bus\r
509 //\r
510 if (IS_PCI_16550SERIAL (Pci)) {\r
511 //\r
512 // Add them to ConOut, ConIn, ErrOut.\r
513 //\r
514 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));\r
515 PreparePciSerialDevicePath (Handle);\r
516 return EFI_SUCCESS;\r
517 }\r
518 }\r
519\r
520 //\r
521 // Here we decide which VGA device to enable in PCI bus\r
522 //\r
523 if (IS_PCI_VGA (Pci)) {\r
524 //\r
525 // Add them to ConOut.\r
526 //\r
527 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));\r
528 PreparePciVgaDevicePath (Handle);\r
529 return EFI_SUCCESS;\r
530 }\r
531\r
532 return Status;\r
533}\r
534\r
535\r
536/**\r
537 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
538\r
539 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.\r
540\r
541 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
542 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
543\r
544**/\r
545EFI_STATUS\r
546DetectAndPreparePlatformPciDevicePaths (\r
547 BOOLEAN DetectVgaOnly\r
548)\r
549{\r
550 mDetectVgaOnly = DetectVgaOnly;\r
551 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
552}\r
553\r
554\r
555/**\r
556 The function will connect root bridge\r
557\r
558 @return EFI_SUCCESS Connect RootBridge successfully.\r
559\r
560**/\r
561EFI_STATUS\r
562ConnectRootBridge (\r
563 VOID\r
564)\r
565{\r
566 EFI_STATUS Status;\r
567 EFI_HANDLE RootHandle;\r
568\r
569 //\r
570 // Make all the PCI_IO protocols on PCI Seg 0 show up\r
571 //\r
572 Status = gBS->LocateDevicePath (\r
573 &gEfiDevicePathProtocolGuid,\r
574 &gPlatformRootBridges[0],\r
575 &RootHandle\r
576 );\r
577 if (EFI_ERROR (Status)) {\r
578 return Status;\r
579 }\r
580\r
581 Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);\r
582 if (EFI_ERROR (Status)) {\r
583 return Status;\r
584 }\r
585\r
586 return EFI_SUCCESS;\r
587}\r
588\r
589/**\r
590 Platform console init. Include the platform firmware vendor, revision\r
591 and so crc check.\r
592\r
593**/\r
594VOID\r
595EFIAPI\r
596PlatformConsoleInit (\r
597 VOID\r
598)\r
599{\r
600 gUartDeviceNode.BaudRate = PcdGet64 (PcdUartDefaultBaudRate);\r
601 gUartDeviceNode.DataBits = PcdGet8 (PcdUartDefaultDataBits);\r
602 gUartDeviceNode.Parity = PcdGet8 (PcdUartDefaultParity);\r
603 gUartDeviceNode.StopBits = PcdGet8 (PcdUartDefaultStopBits);\r
604\r
605 ConnectRootBridge ();\r
606\r
607 //\r
608 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
609 //\r
610 DetectAndPreparePlatformPciDevicePaths (FALSE);\r
611}\r