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