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