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