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