]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformConsole.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 gPnp16550ComPort \
42 PNPID_DEVICE_PATH_NODE(0x0501)
43
44 #define gPnpPs2Keyboard \
45 PNPID_DEVICE_PATH_NODE(0x0303)
46
47 #define gPcAnsiTerminal \
48 { \
49 { \
50 MESSAGING_DEVICE_PATH, \
51 MSG_VENDOR_DP, \
52 { \
53 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
54 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
55 } \
56 }, \
57 DEVICE_PATH_MESSAGING_PC_ANSI \
58 }
59
60 ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
61 ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
62 VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;
63
64 BOOLEAN mDetectDisplayOnly;
65
66 /**
67 Add IsaKeyboard to ConIn.
68
69 @param[in] DeviceHandle Handle of the LPC Bridge device.
70
71 @retval EFI_SUCCESS IsaKeyboard on the LPC bridge have been added to ConIn.
72 @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
73 from DeviceHandle.
74 **/
75 EFI_STATUS
76 PrepareLpcBridgeDevicePath (
77 IN EFI_HANDLE DeviceHandle
78 )
79 {
80 EFI_STATUS Status;
81 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
82
83 DevicePath = NULL;
84 Status = gBS->HandleProtocol (
85 DeviceHandle,
86 &gEfiDevicePathProtocolGuid,
87 (VOID *)&DevicePath
88 );
89 if (EFI_ERROR (Status)) {
90 return Status;
91 }
92
93 //
94 // Register Keyboard
95 //
96 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
97 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
98 return EFI_SUCCESS;
99 }
100
101 /**
102 Return the GOP device path in the platform.
103
104 @param[in] PciDevicePath - Device path for the PCI graphics device.
105 @param[out] GopDevicePath - Return the device path with GOP installed.
106
107 @retval EFI_SUCCESS - PCI VGA is added to ConOut.
108 @retval EFI_INVALID_PARAMETER - The device path parameter is invalid.
109 @retval EFI_STATUS - No GOP device found.
110 **/
111 EFI_STATUS
112 GetGopDevicePath (
113 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
114 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
115 )
116 {
117 UINTN Index;
118 EFI_STATUS Status;
119 EFI_HANDLE PciDeviceHandle;
120 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
121 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
122 UINTN GopHandleCount;
123 EFI_HANDLE *GopHandleBuffer;
124
125 if ((PciDevicePath == NULL) || (GopDevicePath == NULL)) {
126 return EFI_INVALID_PARAMETER;
127 }
128
129 //
130 // Initialize the GopDevicePath to be PciDevicePath
131 //
132 *GopDevicePath = PciDevicePath;
133 TempPciDevicePath = PciDevicePath;
134
135 Status = gBS->LocateDevicePath (
136 &gEfiDevicePathProtocolGuid,
137 &TempPciDevicePath,
138 &PciDeviceHandle
139 );
140 if (EFI_ERROR (Status)) {
141 return Status;
142 }
143
144 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
145
146 Status = gBS->LocateHandleBuffer (
147 ByProtocol,
148 &gEfiGraphicsOutputProtocolGuid,
149 NULL,
150 &GopHandleCount,
151 &GopHandleBuffer
152 );
153 if (!EFI_ERROR (Status)) {
154 //
155 // Add all the child handles as possible Console Device
156 //
157 for (Index = 0; Index < GopHandleCount; Index++) {
158 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *)&TempDevicePath);
159 if (EFI_ERROR (Status)) {
160 continue;
161 }
162
163 if (CompareMem (
164 PciDevicePath,
165 TempDevicePath,
166 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
167 ) == 0)
168 {
169 //
170 // In current implementation, we only enable one of the child handles
171 // as console device, i.e. sotre one of the child handle's device
172 // path to variable "ConOut"
173 // In future, we could select all child handles to be console device
174 //
175 *GopDevicePath = TempDevicePath;
176
177 //
178 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
179 // Add the integrity GOP device path.
180 //
181 EfiBootManagerUpdateConsoleVariable (ConOut, NULL, PciDevicePath);
182 EfiBootManagerUpdateConsoleVariable (ConOut, TempDevicePath, NULL);
183 }
184 }
185
186 gBS->FreePool (GopHandleBuffer);
187 }
188
189 return EFI_SUCCESS;
190 }
191
192 /**
193 Add PCI VGA to ConOut, ConIn, ErrOut.
194
195 @param[in] DeviceHandle - Handle of PciIo protocol.
196
197 @retval EFI_SUCCESS - PCI VGA is added to ConOut.
198 @retval EFI_STATUS - No PCI VGA device is added.
199
200 **/
201 EFI_STATUS
202 PreparePciVgaDevicePath (
203 IN EFI_HANDLE DeviceHandle
204 )
205 {
206 EFI_STATUS Status;
207 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
208 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
209
210 DevicePath = NULL;
211 Status = gBS->HandleProtocol (
212 DeviceHandle,
213 &gEfiDevicePathProtocolGuid,
214 (VOID *)&DevicePath
215 );
216 if (EFI_ERROR (Status)) {
217 return Status;
218 }
219
220 GetGopDevicePath (DevicePath, &GopDevicePath);
221 DevicePath = GopDevicePath;
222
223 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
224
225 return EFI_SUCCESS;
226 }
227
228 /**
229 For every PCI instance execute a callback function.
230
231 @param[in] Id - The protocol GUID for callback
232 @param[in] CallBackFunction - The callback function
233
234 @retval EFI_STATUS - Callback function failed.
235
236 **/
237 EFI_STATUS
238 EFIAPI
239 VisitAllInstancesOfProtocol (
240 IN EFI_GUID *Id,
241 IN SIMPLE_PROTOCOL_INSTANCE_CALLBACK CallBackFunction
242 )
243 {
244 EFI_STATUS Status;
245 UINTN HandleCount;
246 EFI_HANDLE *HandleBuffer;
247 UINTN Index;
248 VOID *Instance;
249
250 //
251 // Start to check all the PciIo to find all possible device
252 //
253 HandleCount = 0;
254 HandleBuffer = NULL;
255 Status = gBS->LocateHandleBuffer (
256 ByProtocol,
257 Id,
258 NULL,
259 &HandleCount,
260 &HandleBuffer
261 );
262 if (EFI_ERROR (Status)) {
263 return Status;
264 }
265
266 for (Index = 0; Index < HandleCount; Index++) {
267 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
268 if (EFI_ERROR (Status)) {
269 continue;
270 }
271
272 Status = (*CallBackFunction)(
273 HandleBuffer[Index],
274 Instance
275 );
276 }
277
278 gBS->FreePool (HandleBuffer);
279
280 return EFI_SUCCESS;
281 }
282
283 /**
284 Do platform specific PCI Device check and add them to
285 ConOut, ConIn, ErrOut.
286
287 @param[in] Handle - Handle of PCI device instance
288 @param[in] Instance - The instance of PCI device
289
290 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
291 @retval EFI_STATUS - PCI Device check or Console variable update fail.
292
293 **/
294 EFI_STATUS
295 EFIAPI
296 DetectAndPreparePlatformPciDevicePath (
297 IN EFI_HANDLE Handle,
298 IN VOID *Instance
299 )
300 {
301 EFI_STATUS Status;
302 EFI_PCI_IO_PROTOCOL *PciIo;
303 PCI_TYPE00 Pci;
304
305 PciIo = (EFI_PCI_IO_PROTOCOL *)Instance;
306
307 //
308 // Check for all PCI device
309 //
310 Status = PciIo->Pci.Read (
311 PciIo,
312 EfiPciIoWidthUint32,
313 0,
314 sizeof (Pci) / sizeof (UINT32),
315 &Pci
316 );
317 if (EFI_ERROR (Status)) {
318 return Status;
319 }
320
321 Status = PciIo->Attributes (
322 PciIo,
323 EfiPciIoAttributeOperationEnable,
324 EFI_PCI_DEVICE_ENABLE,
325 NULL
326 );
327 ASSERT_EFI_ERROR (Status);
328
329 if (!mDetectDisplayOnly) {
330 //
331 // Here we decide whether it is LPC Bridge
332 //
333 if ((IS_PCI_LPC (&Pci)) ||
334 ((IS_PCI_ISA_PDECODE (&Pci)) &&
335 (Pci.Hdr.VendorId == 0x8086)
336 )
337 )
338 {
339 //
340 // Add IsaKeyboard to ConIn,
341 // add IsaSerial to ConOut, ConIn, ErrOut
342 //
343 DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
344 PrepareLpcBridgeDevicePath (Handle);
345 return EFI_SUCCESS;
346 }
347 }
348
349 //
350 // Enable all display devices
351 //
352 if (IS_PCI_DISPLAY (&Pci)) {
353 //
354 // Add them to ConOut.
355 //
356 DEBUG ((DEBUG_INFO, "Found PCI Display device\n"));
357 EfiBootManagerConnectVideoController (Handle);
358 return EFI_SUCCESS;
359 }
360
361 return Status;
362 }
363
364 /**
365 For every Serial Io instance, add it to ConOut, ConIn, ErrOut.
366
367 @param[in] Handle - The Serial Io device handle
368 @param[in] Instance - The instance of the SerialIo protocol
369
370 @retval EFI_STATUS - Callback function failed.
371
372 **/
373 EFI_STATUS
374 EFIAPI
375 AddDevicePathForOneSerialIoInstance (
376 IN EFI_HANDLE Handle,
377 IN VOID *Instance
378 )
379 {
380 EFI_STATUS Status;
381 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
382
383 DevicePath = NULL;
384 Status = gBS->HandleProtocol (
385 Handle,
386 &gEfiDevicePathProtocolGuid,
387 (VOID *)&DevicePath
388 );
389 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
390
391 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
392 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
393 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
394 return Status;
395 }
396
397 /**
398 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
399
400 @param[in] DetectDisplayOnly - Only detect display device if it's TRUE.
401
402 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
403 @retval EFI_STATUS - PCI Device check or Console variable update fail.
404
405 **/
406 EFI_STATUS
407 DetectAndPreparePlatformPciDevicePaths (
408 BOOLEAN DetectDisplayOnly
409 )
410 {
411 EFI_STATUS Status;
412
413 mDetectDisplayOnly = DetectDisplayOnly;
414
415 EfiBootManagerUpdateConsoleVariable (
416 ConIn,
417 (EFI_DEVICE_PATH_PROTOCOL *)&gUsbClassKeyboardDevicePath,
418 NULL
419 );
420
421 VisitAllInstancesOfProtocol (
422 &gEfiSerialIoProtocolGuid,
423 AddDevicePathForOneSerialIoInstance
424 );
425
426 Status = VisitAllInstancesOfProtocol (
427 &gEfiPciIoProtocolGuid,
428 DetectAndPreparePlatformPciDevicePath
429 );
430 return Status;
431 }
432
433 /**
434 The function will connect one root bridge
435
436 @param[in] Handle - The root bridge handle
437 @param[in] Instance - The instance of the root bridge
438
439 @return EFI_SUCCESS Connect RootBridge successfully.
440
441 **/
442 EFI_STATUS
443 EFIAPI
444 ConnectOneRootBridge (
445 IN EFI_HANDLE Handle,
446 IN VOID *Instance
447 )
448 {
449 EFI_STATUS Status;
450
451 Status = gBS->ConnectController (Handle, NULL, NULL, FALSE);
452 if (EFI_ERROR (Status)) {
453 return Status;
454 }
455
456 return EFI_SUCCESS;
457 }
458
459 /**
460 Platform console init. Include the platform firmware vendor, revision
461 and so crc check.
462
463 **/
464 VOID
465 EFIAPI
466 PlatformConsoleInit (
467 VOID
468 )
469 {
470 VisitAllInstancesOfProtocol (
471 &gEfiPciRootBridgeIoProtocolGuid,
472 ConnectOneRootBridge
473 );
474
475 //
476 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
477 //
478 DetectAndPreparePlatformPciDevicePaths (FALSE);
479 }