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