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