]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.c
Add PCD for selecting terminal type at build time
[mirror_edk2.git] / ArmVirtPkg / Library / PlatformIntelBdsLib / IntelBdsPlatform.c
CommitLineData
be8afe14 1/** @file\r
e4fbd18f 2 Implementation for PlatformBdsLib library class interfaces.\r
be8afe14 3\r
60dc18a1 4 Copyright (C) 2015, Red Hat, Inc.\r
e4fbd18f
LE
5 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
6 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>\r
be8afe14 7\r
e4fbd18f
LE
8 This program and the accompanying materials are licensed and made available\r
9 under the terms and conditions of the BSD License which accompanies this\r
10 distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
be8afe14 12\r
e4fbd18f
LE
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
be8afe14
LE
15\r
16**/\r
17\r
60dc18a1
LE
18#include <IndustryStandard/Pci22.h>\r
19#include <Library/DevicePathLib.h>\r
20#include <Library/PcdLib.h>\r
ba67a145 21#include <Library/PlatformBdsLib.h>\r
274b4a8d 22#include <Library/QemuBootOrderLib.h>\r
60dc18a1
LE
23#include <Protocol/DevicePath.h>\r
24#include <Protocol/GraphicsOutput.h>\r
25#include <Protocol/PciIo.h>\r
26#include <Protocol/PciRootBridgeIo.h>\r
9cd7d3c5 27#include <Guid/EventGroup.h>\r
274b4a8d 28\r
ba67a145
LE
29#include "IntelBdsPlatform.h"\r
30\r
60dc18a1
LE
31#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }\r
32\r
33\r
34#pragma pack (1)\r
35typedef struct {\r
36 VENDOR_DEVICE_PATH SerialDxe;\r
37 UART_DEVICE_PATH Uart;\r
a51c1699 38 VENDOR_DEFINED_DEVICE_PATH TermType;\r
60dc18a1
LE
39 EFI_DEVICE_PATH_PROTOCOL End;\r
40} PLATFORM_SERIAL_CONSOLE;\r
41#pragma pack ()\r
42\r
43#define SERIAL_DXE_FILE_GUID { \\r
44 0xD3987D4B, 0x971A, 0x435F, \\r
45 { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \\r
46 }\r
47\r
48STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {\r
49 //\r
50 // VENDOR_DEVICE_PATH SerialDxe\r
51 //\r
52 {\r
53 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },\r
54 SERIAL_DXE_FILE_GUID\r
55 },\r
56\r
57 //\r
58 // UART_DEVICE_PATH Uart\r
59 //\r
60 {\r
61 { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },\r
62 0, // Reserved\r
63 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
64 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
65 FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
66 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
67 },\r
68\r
69 //\r
a51c1699 70 // VENDOR_DEFINED_DEVICE_PATH TermType\r
60dc18a1
LE
71 //\r
72 {\r
73 {\r
74 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,\r
75 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)\r
a51c1699
LE
76 }\r
77 //\r
78 // Guid to be filled in dynamically\r
79 //\r
60dc18a1
LE
80 },\r
81\r
82 //\r
83 // EFI_DEVICE_PATH_PROTOCOL End\r
84 //\r
85 {\r
86 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
87 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
88 }\r
89};\r
90\r
91\r
92#pragma pack (1)\r
93typedef struct {\r
94 USB_CLASS_DEVICE_PATH Keyboard;\r
95 EFI_DEVICE_PATH_PROTOCOL End;\r
96} PLATFORM_USB_KEYBOARD;\r
97#pragma pack ()\r
98\r
99STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {\r
100 //\r
101 // USB_CLASS_DEVICE_PATH Keyboard\r
102 //\r
103 {\r
104 {\r
105 MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,\r
106 DP_NODE_LEN (USB_CLASS_DEVICE_PATH)\r
107 },\r
108 0xFFFF, // VendorId: any\r
109 0xFFFF, // ProductId: any\r
110 3, // DeviceClass: HID\r
111 1, // DeviceSubClass: boot\r
112 1 // DeviceProtocol: keyboard\r
113 },\r
114\r
115 //\r
116 // EFI_DEVICE_PATH_PROTOCOL End\r
117 //\r
118 {\r
119 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
120 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
121 }\r
122};\r
123\r
9cd7d3c5
AB
124/**\r
125 An empty function to pass error checking of CreateEventEx ().\r
126\r
127 @param Event Event whose notification function is being invoked.\r
128 @param Context Pointer to the notification function's context,\r
129 which is implementation-dependent.\r
130\r
131**/\r
132STATIC\r
133VOID\r
134EFIAPI\r
135EmptyCallbackFunction (\r
136 IN EFI_EVENT Event,\r
137 IN VOID *Context\r
138 )\r
139{\r
140}\r
60dc18a1 141\r
be8afe14
LE
142//\r
143// BDS Platform Functions\r
144//\r
145/**\r
146 Platform Bds init. Include the platform firmware vendor, revision\r
147 and so crc check.\r
148\r
149**/\r
150VOID\r
151EFIAPI\r
152PlatformBdsInit (\r
153 VOID\r
154 )\r
155{\r
9cd7d3c5
AB
156 EFI_EVENT EndOfDxeEvent;\r
157 EFI_STATUS Status;\r
158\r
159 //\r
160 // Signal EndOfDxe PI Event\r
161 //\r
162 Status = gBS->CreateEventEx (\r
163 EVT_NOTIFY_SIGNAL,\r
164 TPL_CALLBACK,\r
165 EmptyCallbackFunction,\r
166 NULL,\r
167 &gEfiEndOfDxeEventGroupGuid,\r
168 &EndOfDxeEvent\r
169 );\r
170 if (!EFI_ERROR (Status)) {\r
171 gBS->SignalEvent (EndOfDxeEvent);\r
172 gBS->CloseEvent (EndOfDxeEvent);\r
173 }\r
be8afe14
LE
174}\r
175\r
60dc18a1
LE
176\r
177/**\r
178 Check if the handle satisfies a particular condition.\r
179\r
180 @param[in] Handle The handle to check.\r
181 @param[in] ReportText A caller-allocated string passed in for reporting\r
182 purposes. It must never be NULL.\r
183\r
184 @retval TRUE The condition is satisfied.\r
185 @retval FALSE Otherwise. This includes the case when the condition could not\r
186 be fully evaluated due to an error.\r
187**/\r
188typedef\r
189BOOLEAN\r
190(EFIAPI *FILTER_FUNCTION) (\r
191 IN EFI_HANDLE Handle,\r
192 IN CONST CHAR16 *ReportText\r
193 );\r
194\r
195\r
196/**\r
197 Process a handle.\r
198\r
199 @param[in] Handle The handle to process.\r
200 @param[in] ReportText A caller-allocated string passed in for reporting\r
201 purposes. It must never be NULL.\r
202**/\r
203typedef\r
204VOID\r
205(EFIAPI *CALLBACK_FUNCTION) (\r
206 IN EFI_HANDLE Handle,\r
207 IN CONST CHAR16 *ReportText\r
208 );\r
209\r
210/**\r
211 Locate all handles that carry the specified protocol, filter them with a\r
212 callback function, and pass each handle that passes the filter to another\r
213 callback.\r
214\r
215 @param[in] ProtocolGuid The protocol to look for.\r
216\r
217 @param[in] Filter The filter function to pass each handle to. If this\r
218 parameter is NULL, then all handles are processed.\r
219\r
220 @param[in] Process The callback function to pass each handle to that\r
221 clears the filter.\r
222**/\r
223STATIC\r
224VOID\r
225FilterAndProcess (\r
226 IN EFI_GUID *ProtocolGuid,\r
227 IN FILTER_FUNCTION Filter OPTIONAL,\r
228 IN CALLBACK_FUNCTION Process\r
229 )\r
230{\r
231 EFI_STATUS Status;\r
232 EFI_HANDLE *Handles;\r
233 UINTN NoHandles;\r
234 UINTN Idx;\r
235\r
236 Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,\r
237 NULL /* SearchKey */, &NoHandles, &Handles);\r
238 if (EFI_ERROR (Status)) {\r
239 //\r
240 // This is not an error, just an informative condition.\r
241 //\r
242 DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,\r
243 Status));\r
244 return;\r
245 }\r
246\r
247 ASSERT (NoHandles > 0);\r
248 for (Idx = 0; Idx < NoHandles; ++Idx) {\r
249 CHAR16 *DevicePathText;\r
250 STATIC CHAR16 Fallback[] = L"<device path unavailable>";\r
251\r
252 //\r
253 // The ConvertDevicePathToText() function handles NULL input transparently.\r
254 //\r
255 DevicePathText = ConvertDevicePathToText (\r
256 DevicePathFromHandle (Handles[Idx]),\r
257 FALSE, // DisplayOnly\r
258 FALSE // AllowShortcuts\r
259 );\r
260 if (DevicePathText == NULL) {\r
261 DevicePathText = Fallback;\r
262 }\r
263\r
264 if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {\r
265 Process (Handles[Idx], DevicePathText);\r
266 }\r
267\r
268 if (DevicePathText != Fallback) {\r
269 FreePool (DevicePathText);\r
270 }\r
271 }\r
272 gBS->FreePool (Handles);\r
273}\r
274\r
275\r
276/**\r
277 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
278**/\r
279STATIC\r
280BOOLEAN\r
281EFIAPI\r
282IsPciDisplay (\r
283 IN EFI_HANDLE Handle,\r
284 IN CONST CHAR16 *ReportText\r
285 )\r
286{\r
287 EFI_STATUS Status;\r
288 EFI_PCI_IO_PROTOCOL *PciIo;\r
289 PCI_TYPE00 Pci;\r
290\r
291 Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,\r
292 (VOID**)&PciIo);\r
293 if (EFI_ERROR (Status)) {\r
294 //\r
295 // This is not an error worth reporting.\r
296 //\r
297 return FALSE;\r
298 }\r
299\r
300 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,\r
301 sizeof Pci / sizeof (UINT32), &Pci);\r
302 if (EFI_ERROR (Status)) {\r
303 DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));\r
304 return FALSE;\r
305 }\r
306\r
307 return IS_PCI_DISPLAY (&Pci);\r
308}\r
309\r
310\r
311/**\r
312 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
313 the matching driver to produce all first-level child handles.\r
314**/\r
315STATIC\r
316VOID\r
317EFIAPI\r
318Connect (\r
319 IN EFI_HANDLE Handle,\r
320 IN CONST CHAR16 *ReportText\r
321 )\r
322{\r
323 EFI_STATUS Status;\r
324\r
325 Status = gBS->ConnectController (\r
326 Handle, // ControllerHandle\r
327 NULL, // DriverImageHandle\r
328 NULL, // RemainingDevicePath -- produce all children\r
329 FALSE // Recursive\r
330 );\r
331 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",\r
332 __FUNCTION__, ReportText, Status));\r
333}\r
334\r
335\r
336/**\r
337 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
338 handle, and adds it to ConOut and ErrOut.\r
339**/\r
340STATIC\r
341VOID\r
342EFIAPI\r
343AddOutput (\r
344 IN EFI_HANDLE Handle,\r
345 IN CONST CHAR16 *ReportText\r
346 )\r
347{\r
348 EFI_STATUS Status;\r
349 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
350\r
351 DevicePath = DevicePathFromHandle (Handle);\r
352 if (DevicePath == NULL) {\r
353 DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",\r
354 __FUNCTION__, ReportText, Handle));\r
355 return;\r
356 }\r
357\r
358 Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL);\r
359 if (EFI_ERROR (Status)) {\r
360 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,\r
361 ReportText, Status));\r
362 return;\r
363 }\r
364\r
365 Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL);\r
366 if (EFI_ERROR (Status)) {\r
367 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,\r
368 ReportText, Status));\r
369 return;\r
370 }\r
371\r
372 DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,\r
373 ReportText));\r
374}\r
375\r
376\r
be8afe14
LE
377/**\r
378 The function will execute with as the platform policy, current policy\r
379 is driven by boot mode. IBV/OEM can customize this code for their specific\r
380 policy action.\r
381\r
382 @param DriverOptionList The header of the driver option link list\r
383 @param BootOptionList The header of the boot option link list\r
384 @param ProcessCapsules A pointer to ProcessCapsules()\r
385 @param BaseMemoryTest A pointer to BaseMemoryTest()\r
386\r
387**/\r
388VOID\r
389EFIAPI\r
390PlatformBdsPolicyBehavior (\r
391 IN LIST_ENTRY *DriverOptionList,\r
392 IN LIST_ENTRY *BootOptionList,\r
393 IN PROCESS_CAPSULES ProcessCapsules,\r
394 IN BASEM_MEMORY_TEST BaseMemoryTest\r
395 )\r
396{\r
60dc18a1
LE
397 //\r
398 // Locate the PCI root bridges and make the PCI bus driver connect each,\r
399 // non-recursively. This will produce a number of child handles with PciIo on\r
400 // them.\r
401 //\r
402 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
403\r
404 //\r
405 // Find all display class PCI devices (using the handles from the previous\r
406 // step), and connect them non-recursively. This should produce a number of\r
407 // child handles with GOPs on them.\r
408 //\r
409 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
410\r
411 //\r
412 // Now add the device path of all handles with GOP on them to ConOut and\r
413 // ErrOut.\r
414 //\r
415 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
416\r
417 //\r
418 // Add the hardcoded short-form USB keyboard device path to ConIn.\r
419 //\r
420 BdsLibUpdateConsoleVariable (L"ConIn",\r
421 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);\r
422\r
423 //\r
424 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
425 //\r
a51c1699
LE
426 CopyGuid (&mSerialConsole.TermType.Guid,\r
427 PcdGetPtr (PcdTerminalTypeGuidBuffer));\r
60dc18a1
LE
428 BdsLibUpdateConsoleVariable (L"ConIn",\r
429 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
430 BdsLibUpdateConsoleVariable (L"ConOut",\r
431 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
432 BdsLibUpdateConsoleVariable (L"ErrOut",\r
433 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
434\r
435 //\r
436 // Connect the consoles based on the above variables.\r
437 //\r
438 BdsLibConnectAllDefaultConsoles ();\r
439\r
26a36374
LE
440 //\r
441 // Show the splash screen.\r
442 //\r
443 EnableQuietBoot (PcdGetPtr (PcdLogoFile));\r
444\r
60dc18a1
LE
445 //\r
446 // Connect the rest of the devices.\r
447 //\r
a78c4836
LE
448 BdsLibConnectAll ();\r
449\r
23d04b58 450 //\r
a78c4836
LE
451 // Process QEMU's -kernel command line option. Note that the kernel booted\r
452 // this way should receive ACPI tables, which is why we connect all devices\r
453 // first (see above) -- PCI enumeration blocks ACPI table installation, if\r
454 // there is a PCI host.\r
23d04b58
LE
455 //\r
456 TryRunningQemuKernel ();\r
457\r
1b610ac2 458 BdsLibEnumerateAllBootOption (BootOptionList);\r
274b4a8d
LE
459 SetBootOrderFromQemu (BootOptionList);\r
460 //\r
461 // The BootOrder variable may have changed, reload the in-memory list with\r
462 // it.\r
463 //\r
464 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
465\r
9aaf441c 466 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);\r
be8afe14
LE
467}\r
468\r
469/**\r
470 Hook point after a boot attempt succeeds. We don't expect a boot option to\r
471 return, so the UEFI 2.0 specification defines that you will default to an\r
472 interactive mode and stop processing the BootOrder list in this case. This\r
473 is also a platform implementation and can be customized by IBV/OEM.\r
474\r
475 @param Option Pointer to Boot Option that succeeded to boot.\r
476\r
477**/\r
478VOID\r
479EFIAPI\r
480PlatformBdsBootSuccess (\r
481 IN BDS_COMMON_OPTION *Option\r
482 )\r
483{\r
484}\r
485\r
486/**\r
487 Hook point after a boot attempt fails.\r
488\r
489 @param Option Pointer to Boot Option that failed to boot.\r
490 @param Status Status returned from failed boot.\r
491 @param ExitData Exit data returned from failed boot.\r
492 @param ExitDataSize Exit data size returned from failed boot.\r
493\r
494**/\r
495VOID\r
496EFIAPI\r
497PlatformBdsBootFail (\r
498 IN BDS_COMMON_OPTION *Option,\r
499 IN EFI_STATUS Status,\r
500 IN CHAR16 *ExitData,\r
501 IN UINTN ExitDataSize\r
502 )\r
503{\r
504}\r
505\r
506/**\r
507 This function locks platform flash that is not allowed to be updated during normal boot path.\r
508 The flash layout is platform specific.\r
509**/\r
510VOID\r
511EFIAPI\r
512PlatformBdsLockNonUpdatableFlash (\r
513 VOID\r
514 )\r
515{\r
516 return;\r
517}\r