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