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