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