]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/Library/PlatformIntelBdsLib/IntelBdsPlatform.c
ArmVirtPkg/PlatformIntelBdsLib: rebase to EfiEventGroupSignal
[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
be8afe14
LE
124//\r
125// BDS Platform Functions\r
126//\r
127/**\r
128 Platform Bds init. Include the platform firmware vendor, revision\r
129 and so crc check.\r
130\r
131**/\r
132VOID\r
133EFIAPI\r
134PlatformBdsInit (\r
135 VOID\r
136 )\r
137{\r
9cd7d3c5
AB
138 //\r
139 // Signal EndOfDxe PI Event\r
140 //\r
dfc95147 141 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
be8afe14
LE
142}\r
143\r
60dc18a1
LE
144\r
145/**\r
146 Check if the handle satisfies a particular condition.\r
147\r
148 @param[in] Handle The handle to check.\r
149 @param[in] ReportText A caller-allocated string passed in for reporting\r
150 purposes. It must never be NULL.\r
151\r
152 @retval TRUE The condition is satisfied.\r
153 @retval FALSE Otherwise. This includes the case when the condition could not\r
154 be fully evaluated due to an error.\r
155**/\r
156typedef\r
157BOOLEAN\r
158(EFIAPI *FILTER_FUNCTION) (\r
159 IN EFI_HANDLE Handle,\r
160 IN CONST CHAR16 *ReportText\r
161 );\r
162\r
163\r
164/**\r
165 Process a handle.\r
166\r
167 @param[in] Handle The handle to process.\r
168 @param[in] ReportText A caller-allocated string passed in for reporting\r
169 purposes. It must never be NULL.\r
170**/\r
171typedef\r
172VOID\r
173(EFIAPI *CALLBACK_FUNCTION) (\r
174 IN EFI_HANDLE Handle,\r
175 IN CONST CHAR16 *ReportText\r
176 );\r
177\r
178/**\r
179 Locate all handles that carry the specified protocol, filter them with a\r
180 callback function, and pass each handle that passes the filter to another\r
181 callback.\r
182\r
183 @param[in] ProtocolGuid The protocol to look for.\r
184\r
185 @param[in] Filter The filter function to pass each handle to. If this\r
186 parameter is NULL, then all handles are processed.\r
187\r
188 @param[in] Process The callback function to pass each handle to that\r
189 clears the filter.\r
190**/\r
191STATIC\r
192VOID\r
193FilterAndProcess (\r
194 IN EFI_GUID *ProtocolGuid,\r
195 IN FILTER_FUNCTION Filter OPTIONAL,\r
196 IN CALLBACK_FUNCTION Process\r
197 )\r
198{\r
199 EFI_STATUS Status;\r
200 EFI_HANDLE *Handles;\r
201 UINTN NoHandles;\r
202 UINTN Idx;\r
203\r
204 Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,\r
205 NULL /* SearchKey */, &NoHandles, &Handles);\r
206 if (EFI_ERROR (Status)) {\r
207 //\r
208 // This is not an error, just an informative condition.\r
209 //\r
210 DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,\r
211 Status));\r
212 return;\r
213 }\r
214\r
215 ASSERT (NoHandles > 0);\r
216 for (Idx = 0; Idx < NoHandles; ++Idx) {\r
217 CHAR16 *DevicePathText;\r
218 STATIC CHAR16 Fallback[] = L"<device path unavailable>";\r
219\r
220 //\r
221 // The ConvertDevicePathToText() function handles NULL input transparently.\r
222 //\r
223 DevicePathText = ConvertDevicePathToText (\r
224 DevicePathFromHandle (Handles[Idx]),\r
225 FALSE, // DisplayOnly\r
226 FALSE // AllowShortcuts\r
227 );\r
228 if (DevicePathText == NULL) {\r
229 DevicePathText = Fallback;\r
230 }\r
231\r
232 if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {\r
233 Process (Handles[Idx], DevicePathText);\r
234 }\r
235\r
236 if (DevicePathText != Fallback) {\r
237 FreePool (DevicePathText);\r
238 }\r
239 }\r
240 gBS->FreePool (Handles);\r
241}\r
242\r
243\r
244/**\r
245 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
246**/\r
247STATIC\r
248BOOLEAN\r
249EFIAPI\r
250IsPciDisplay (\r
251 IN EFI_HANDLE Handle,\r
252 IN CONST CHAR16 *ReportText\r
253 )\r
254{\r
255 EFI_STATUS Status;\r
256 EFI_PCI_IO_PROTOCOL *PciIo;\r
257 PCI_TYPE00 Pci;\r
258\r
259 Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,\r
260 (VOID**)&PciIo);\r
261 if (EFI_ERROR (Status)) {\r
262 //\r
263 // This is not an error worth reporting.\r
264 //\r
265 return FALSE;\r
266 }\r
267\r
268 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,\r
269 sizeof Pci / sizeof (UINT32), &Pci);\r
270 if (EFI_ERROR (Status)) {\r
271 DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));\r
272 return FALSE;\r
273 }\r
274\r
275 return IS_PCI_DISPLAY (&Pci);\r
276}\r
277\r
278\r
279/**\r
280 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
281 the matching driver to produce all first-level child handles.\r
282**/\r
283STATIC\r
284VOID\r
285EFIAPI\r
286Connect (\r
287 IN EFI_HANDLE Handle,\r
288 IN CONST CHAR16 *ReportText\r
289 )\r
290{\r
291 EFI_STATUS Status;\r
292\r
293 Status = gBS->ConnectController (\r
294 Handle, // ControllerHandle\r
295 NULL, // DriverImageHandle\r
296 NULL, // RemainingDevicePath -- produce all children\r
297 FALSE // Recursive\r
298 );\r
299 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",\r
300 __FUNCTION__, ReportText, Status));\r
301}\r
302\r
303\r
304/**\r
305 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
306 handle, and adds it to ConOut and ErrOut.\r
307**/\r
308STATIC\r
309VOID\r
310EFIAPI\r
311AddOutput (\r
312 IN EFI_HANDLE Handle,\r
313 IN CONST CHAR16 *ReportText\r
314 )\r
315{\r
316 EFI_STATUS Status;\r
317 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
318\r
319 DevicePath = DevicePathFromHandle (Handle);\r
320 if (DevicePath == NULL) {\r
321 DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",\r
322 __FUNCTION__, ReportText, Handle));\r
323 return;\r
324 }\r
325\r
326 Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL);\r
327 if (EFI_ERROR (Status)) {\r
328 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,\r
329 ReportText, Status));\r
330 return;\r
331 }\r
332\r
333 Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL);\r
334 if (EFI_ERROR (Status)) {\r
335 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,\r
336 ReportText, Status));\r
337 return;\r
338 }\r
339\r
340 DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,\r
341 ReportText));\r
342}\r
343\r
344\r
be8afe14
LE
345/**\r
346 The function will execute with as the platform policy, current policy\r
347 is driven by boot mode. IBV/OEM can customize this code for their specific\r
348 policy action.\r
349\r
350 @param DriverOptionList The header of the driver option link list\r
351 @param BootOptionList The header of the boot option link list\r
352 @param ProcessCapsules A pointer to ProcessCapsules()\r
353 @param BaseMemoryTest A pointer to BaseMemoryTest()\r
354\r
355**/\r
356VOID\r
357EFIAPI\r
358PlatformBdsPolicyBehavior (\r
359 IN LIST_ENTRY *DriverOptionList,\r
360 IN LIST_ENTRY *BootOptionList,\r
361 IN PROCESS_CAPSULES ProcessCapsules,\r
362 IN BASEM_MEMORY_TEST BaseMemoryTest\r
363 )\r
364{\r
60dc18a1
LE
365 //\r
366 // Locate the PCI root bridges and make the PCI bus driver connect each,\r
367 // non-recursively. This will produce a number of child handles with PciIo on\r
368 // them.\r
369 //\r
370 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
371\r
372 //\r
373 // Find all display class PCI devices (using the handles from the previous\r
374 // step), and connect them non-recursively. This should produce a number of\r
375 // child handles with GOPs on them.\r
376 //\r
377 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
378\r
379 //\r
380 // Now add the device path of all handles with GOP on them to ConOut and\r
381 // ErrOut.\r
382 //\r
383 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
384\r
385 //\r
386 // Add the hardcoded short-form USB keyboard device path to ConIn.\r
387 //\r
388 BdsLibUpdateConsoleVariable (L"ConIn",\r
389 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);\r
390\r
391 //\r
392 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
393 //\r
a51c1699
LE
394 CopyGuid (&mSerialConsole.TermType.Guid,\r
395 PcdGetPtr (PcdTerminalTypeGuidBuffer));\r
60dc18a1
LE
396 BdsLibUpdateConsoleVariable (L"ConIn",\r
397 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
398 BdsLibUpdateConsoleVariable (L"ConOut",\r
399 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
400 BdsLibUpdateConsoleVariable (L"ErrOut",\r
401 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
402\r
403 //\r
404 // Connect the consoles based on the above variables.\r
405 //\r
406 BdsLibConnectAllDefaultConsoles ();\r
407\r
26a36374
LE
408 //\r
409 // Show the splash screen.\r
410 //\r
411 EnableQuietBoot (PcdGetPtr (PcdLogoFile));\r
412\r
60dc18a1
LE
413 //\r
414 // Connect the rest of the devices.\r
415 //\r
a78c4836
LE
416 BdsLibConnectAll ();\r
417\r
23d04b58 418 //\r
a78c4836
LE
419 // Process QEMU's -kernel command line option. Note that the kernel booted\r
420 // this way should receive ACPI tables, which is why we connect all devices\r
421 // first (see above) -- PCI enumeration blocks ACPI table installation, if\r
422 // there is a PCI host.\r
23d04b58
LE
423 //\r
424 TryRunningQemuKernel ();\r
425\r
1b610ac2 426 BdsLibEnumerateAllBootOption (BootOptionList);\r
274b4a8d
LE
427 SetBootOrderFromQemu (BootOptionList);\r
428 //\r
429 // The BootOrder variable may have changed, reload the in-memory list with\r
430 // it.\r
431 //\r
432 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
433\r
9aaf441c 434 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);\r
be8afe14
LE
435}\r
436\r
437/**\r
438 Hook point after a boot attempt succeeds. We don't expect a boot option to\r
439 return, so the UEFI 2.0 specification defines that you will default to an\r
440 interactive mode and stop processing the BootOrder list in this case. This\r
441 is also a platform implementation and can be customized by IBV/OEM.\r
442\r
443 @param Option Pointer to Boot Option that succeeded to boot.\r
444\r
445**/\r
446VOID\r
447EFIAPI\r
448PlatformBdsBootSuccess (\r
449 IN BDS_COMMON_OPTION *Option\r
450 )\r
451{\r
452}\r
453\r
454/**\r
455 Hook point after a boot attempt fails.\r
456\r
457 @param Option Pointer to Boot Option that failed to boot.\r
458 @param Status Status returned from failed boot.\r
459 @param ExitData Exit data returned from failed boot.\r
460 @param ExitDataSize Exit data size returned from failed boot.\r
461\r
462**/\r
463VOID\r
464EFIAPI\r
465PlatformBdsBootFail (\r
466 IN BDS_COMMON_OPTION *Option,\r
467 IN EFI_STATUS Status,\r
468 IN CHAR16 *ExitData,\r
469 IN UINTN ExitDataSize\r
470 )\r
471{\r
472}\r
473\r
474/**\r
475 This function locks platform flash that is not allowed to be updated during normal boot path.\r
476 The flash layout is platform specific.\r
477**/\r
478VOID\r
479EFIAPI\r
480PlatformBdsLockNonUpdatableFlash (\r
481 VOID\r
482 )\r
483{\r
484 return;\r
485}\r