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