]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
EmulatorPkg: Fix typos in comments and variables
[mirror_edk2.git] / OvmfPkg / Library / PlatformBootManagerLib / BdsPlatform.c
CommitLineData
30541881
RN
1/** @file\r
2 Platform BDS customizations.\r
3\r
a7566234 4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
30541881
RN
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "BdsPlatform.h"\r
da2369d2 16#include <Guid/XenInfo.h>\r
30541881 17#include <Guid/RootBridgesConnectedEventGroup.h>\r
2eb35898 18#include <Protocol/FirmwareVolume2.h>\r
30541881
RN
19\r
20\r
21//\r
22// Global data\r
23//\r
24\r
25VOID *mEfiDevPathNotifyReg;\r
26EFI_EVENT mEfiDevPathEvent;\r
27VOID *mEmuVariableEventReg;\r
28EFI_EVENT mEmuVariableEvent;\r
29BOOLEAN mDetectVgaOnly;\r
30UINT16 mHostBridgeDevId;\r
31\r
32//\r
33// Table of host IRQs matching PCI IRQs A-D\r
34// (for configuring PCI Interrupt Line register)\r
35//\r
36CONST UINT8 PciHostIrqs[] = {\r
37 0x0a, 0x0a, 0x0b, 0x0b\r
38};\r
39\r
40//\r
41// Array Size macro\r
42//\r
43#define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))\r
44\r
45//\r
46// Type definitions\r
47//\r
48\r
49typedef\r
50EFI_STATUS\r
51(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(\r
52 IN EFI_HANDLE Handle,\r
53 IN VOID *Instance,\r
54 IN VOID *Context\r
55 );\r
56\r
57/**\r
58 @param[in] Handle - Handle of PCI device instance\r
59 @param[in] PciIo - PCI IO protocol instance\r
60 @param[in] Pci - PCI Header register block\r
61**/\r
62typedef\r
63EFI_STATUS\r
64(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(\r
65 IN EFI_HANDLE Handle,\r
66 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
67 IN PCI_TYPE00 *Pci\r
68 );\r
69\r
70\r
71//\r
72// Function prototypes\r
73//\r
74\r
75EFI_STATUS\r
76VisitAllInstancesOfProtocol (\r
77 IN EFI_GUID *Id,\r
78 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
79 IN VOID *Context\r
80 );\r
81\r
82EFI_STATUS\r
83VisitAllPciInstancesOfProtocol (\r
84 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
85 );\r
86\r
87VOID\r
88InstallDevicePathCallback (\r
89 VOID\r
90 );\r
91\r
07dd96e8
RN
92VOID\r
93PlatformRegisterFvBootOption (\r
94 EFI_GUID *FileGuid,\r
95 CHAR16 *Description,\r
96 UINT32 Attributes\r
97 )\r
98{\r
99 EFI_STATUS Status;\r
100 INTN OptionIndex;\r
101 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
102 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
103 UINTN BootOptionCount;\r
104 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
105 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
106 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
107\r
108 Status = gBS->HandleProtocol (\r
109 gImageHandle,\r
110 &gEfiLoadedImageProtocolGuid,\r
111 (VOID **) &LoadedImage\r
112 );\r
113 ASSERT_EFI_ERROR (Status);\r
114\r
115 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
116 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);\r
117 ASSERT (DevicePath != NULL);\r
118 DevicePath = AppendDevicePathNode (\r
119 DevicePath,\r
120 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
121 );\r
122 ASSERT (DevicePath != NULL);\r
123\r
124 Status = EfiBootManagerInitializeLoadOption (\r
125 &NewOption,\r
126 LoadOptionNumberUnassigned,\r
127 LoadOptionTypeBoot,\r
128 Attributes,\r
129 Description,\r
130 DevicePath,\r
131 NULL,\r
132 0\r
133 );\r
134 ASSERT_EFI_ERROR (Status);\r
135 FreePool (DevicePath);\r
136\r
137 BootOptions = EfiBootManagerGetLoadOptions (\r
138 &BootOptionCount, LoadOptionTypeBoot\r
139 );\r
140\r
141 OptionIndex = EfiBootManagerFindLoadOption (\r
142 &NewOption, BootOptions, BootOptionCount\r
143 );\r
144\r
145 if (OptionIndex == -1) {\r
146 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);\r
147 ASSERT_EFI_ERROR (Status);\r
148 }\r
149 EfiBootManagerFreeLoadOption (&NewOption);\r
150 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
151}\r
152\r
2eb35898
LE
153/**\r
154 Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options\r
155 whose device paths do not resolve exactly to an FvFile in the system.\r
156\r
157 This removes any boot options that point to binaries built into the firmware\r
158 and have become stale due to any of the following:\r
159 - DXEFV's base address or size changed (historical),\r
160 - DXEFV's FvNameGuid changed,\r
161 - the FILE_GUID of the pointed-to binary changed,\r
162 - the referenced binary is no longer built into the firmware.\r
163\r
164 EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only\r
165 avoids exact duplicates.\r
166**/\r
167VOID\r
168RemoveStaleFvFileOptions (\r
169 VOID\r
170 )\r
171{\r
172 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
173 UINTN BootOptionCount;\r
174 UINTN Index;\r
175\r
176 BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,\r
177 LoadOptionTypeBoot);\r
178\r
179 for (Index = 0; Index < BootOptionCount; ++Index) {\r
180 EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;\r
181 EFI_STATUS Status;\r
182 EFI_HANDLE FvHandle;\r
183\r
184 //\r
185 // If the device path starts with neither MemoryMapped(...) nor Fv(...),\r
186 // then keep the boot option.\r
187 //\r
188 Node1 = BootOptions[Index].FilePath;\r
189 if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&\r
190 DevicePathSubType (Node1) == HW_MEMMAP_DP) &&\r
191 !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&\r
192 DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {\r
193 continue;\r
194 }\r
195\r
196 //\r
197 // If the second device path node is not FvFile(...), then keep the boot\r
198 // option.\r
199 //\r
200 Node2 = NextDevicePathNode (Node1);\r
201 if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||\r
202 DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {\r
203 continue;\r
204 }\r
205\r
206 //\r
207 // Locate the Firmware Volume2 protocol instance that is denoted by the\r
208 // boot option. If this lookup fails (i.e., the boot option references a\r
209 // firmware volume that doesn't exist), then we'll proceed to delete the\r
210 // boot option.\r
211 //\r
212 SearchNode = Node1;\r
213 Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,\r
214 &SearchNode, &FvHandle);\r
215\r
216 if (!EFI_ERROR (Status)) {\r
217 //\r
218 // The firmware volume was found; now let's see if it contains the FvFile\r
219 // identified by GUID.\r
220 //\r
221 EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;\r
222 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;\r
223 UINTN BufferSize;\r
224 EFI_FV_FILETYPE FoundType;\r
225 EFI_FV_FILE_ATTRIBUTES FileAttributes;\r
226 UINT32 AuthenticationStatus;\r
227\r
228 Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,\r
229 (VOID **)&FvProtocol);\r
230 ASSERT_EFI_ERROR (Status);\r
231\r
232 FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;\r
233 //\r
234 // Buffer==NULL means we request metadata only: BufferSize, FoundType,\r
235 // FileAttributes.\r
236 //\r
237 Status = FvProtocol->ReadFile (\r
238 FvProtocol,\r
239 &FvFileNode->FvFileName, // NameGuid\r
240 NULL, // Buffer\r
241 &BufferSize,\r
242 &FoundType,\r
243 &FileAttributes,\r
244 &AuthenticationStatus\r
245 );\r
246 if (!EFI_ERROR (Status)) {\r
247 //\r
248 // The FvFile was found. Keep the boot option.\r
249 //\r
250 continue;\r
251 }\r
252 }\r
253\r
254 //\r
255 // Delete the boot option.\r
256 //\r
257 Status = EfiBootManagerDeleteLoadOptionVariable (\r
258 BootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
259 DEBUG_CODE (\r
260 CHAR16 *DevicePathString;\r
261\r
262 DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,\r
263 FALSE, FALSE);\r
264 DEBUG ((\r
265 EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_VERBOSE,\r
266 "%a: removing stale Boot#%04x %s: %r\n",\r
267 __FUNCTION__,\r
268 (UINT32)BootOptions[Index].OptionNumber,\r
269 DevicePathString == NULL ? L"<unavailable>" : DevicePathString,\r
270 Status\r
271 ));\r
272 if (DevicePathString != NULL) {\r
273 FreePool (DevicePathString);\r
274 }\r
275 );\r
276 }\r
277\r
278 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
279}\r
280\r
07dd96e8
RN
281VOID\r
282PlatformRegisterOptionsAndKeys (\r
283 VOID\r
284 )\r
285{\r
286 EFI_STATUS Status;\r
287 EFI_INPUT_KEY Enter;\r
288 EFI_INPUT_KEY F2;\r
289 EFI_INPUT_KEY Esc;\r
290 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
291\r
292 //\r
293 // Register ENTER as CONTINUE key\r
294 //\r
295 Enter.ScanCode = SCAN_NULL;\r
296 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
297 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
298 ASSERT_EFI_ERROR (Status);\r
299\r
300 //\r
301 // Map F2 to Boot Manager Menu\r
302 //\r
303 F2.ScanCode = SCAN_F2;\r
304 F2.UnicodeChar = CHAR_NULL;\r
305 Esc.ScanCode = SCAN_ESC;\r
306 Esc.UnicodeChar = CHAR_NULL;\r
307 Status = EfiBootManagerGetBootManagerMenu (&BootOption);\r
308 ASSERT_EFI_ERROR (Status);\r
309 Status = EfiBootManagerAddKeyOptionVariable (\r
310 NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL\r
311 );\r
312 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
313 Status = EfiBootManagerAddKeyOptionVariable (\r
314 NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL\r
315 );\r
316 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
07dd96e8
RN
317}\r
318\r
30541881
RN
319EFI_STATUS\r
320EFIAPI\r
321ConnectRootBridge (\r
322 IN EFI_HANDLE RootBridgeHandle,\r
323 IN VOID *Instance,\r
324 IN VOID *Context\r
325 );\r
326\r
327STATIC\r
328VOID\r
329SaveS3BootScript (\r
330 VOID\r
331 );\r
332\r
333//\r
334// BDS Platform Functions\r
335//\r
336VOID\r
337EFIAPI\r
a7566234 338PlatformBootManagerBeforeConsole (\r
30541881
RN
339 VOID\r
340 )\r
341/*++\r
342\r
343Routine Description:\r
344\r
345 Platform Bds init. Incude the platform firmware vendor, revision\r
346 and so crc check.\r
347\r
348Arguments:\r
349\r
350Returns:\r
351\r
352 None.\r
353\r
354--*/\r
355{\r
356 EFI_HANDLE Handle;\r
357 EFI_STATUS Status;\r
358\r
a7566234 359 DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));\r
30541881
RN
360 InstallDevicePathCallback ();\r
361\r
362 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,\r
363 ConnectRootBridge, NULL);\r
364\r
365 //\r
366 // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
367 //\r
368 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
369\r
370 //\r
371 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers\r
372 // the preparation of S3 system information. That logic has a hard dependency\r
373 // on the presence of the FACS ACPI table. Since our ACPI tables are only\r
374 // installed after PCI enumeration completes, we must not trigger the S3 save\r
375 // earlier, hence we can't signal End-of-Dxe earlier.\r
376 //\r
377 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
378\r
379 if (QemuFwCfgS3Enabled ()) {\r
380 //\r
381 // Save the boot script too. Note that this will require us to emit the\r
382 // DxeSmmReadyToLock event just below, which in turn locks down SMM.\r
383 //\r
384 SaveS3BootScript ();\r
385 }\r
386\r
387 //\r
388 // Prevent further changes to LockBoxes or SMRAM.\r
389 //\r
390 Handle = NULL;\r
391 Status = gBS->InstallProtocolInterface (&Handle,\r
392 &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,\r
393 NULL);\r
394 ASSERT_EFI_ERROR (Status);\r
e9e9ad64
RN
395\r
396 PlatformInitializeConsole (gPlatformConsole);\r
8dc0f0a6 397 PcdSet16 (PcdPlatformBootTimeOut, GetFrontPageTimeoutFromQemu ());\r
07dd96e8
RN
398\r
399 PlatformRegisterOptionsAndKeys ();\r
30541881
RN
400}\r
401\r
402\r
403EFI_STATUS\r
404EFIAPI\r
405ConnectRootBridge (\r
406 IN EFI_HANDLE RootBridgeHandle,\r
407 IN VOID *Instance,\r
408 IN VOID *Context\r
409 )\r
410{\r
411 EFI_STATUS Status;\r
412\r
413 //\r
414 // Make the PCI bus driver connect the root bridge, non-recursively. This\r
415 // will produce a number of child handles with PciIo on them.\r
416 //\r
417 Status = gBS->ConnectController (\r
418 RootBridgeHandle, // ControllerHandle\r
419 NULL, // DriverImageHandle\r
420 NULL, // RemainingDevicePath -- produce all\r
421 // children\r
422 FALSE // Recursive\r
423 );\r
424 return Status;\r
425}\r
426\r
427\r
428EFI_STATUS\r
429PrepareLpcBridgeDevicePath (\r
430 IN EFI_HANDLE DeviceHandle\r
431 )\r
432/*++\r
433\r
434Routine Description:\r
435\r
436 Add IsaKeyboard to ConIn,\r
437 add IsaSerial to ConOut, ConIn, ErrOut.\r
438 LPC Bridge: 06 01 00\r
439\r
440Arguments:\r
441\r
442 DeviceHandle - Handle of PCIIO protocol.\r
443\r
444Returns:\r
445\r
446 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.\r
447 EFI_STATUS - No LPC bridge is added.\r
448\r
449--*/\r
450{\r
451 EFI_STATUS Status;\r
452 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
453 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
454 CHAR16 *DevPathStr;\r
455\r
456 DevicePath = NULL;\r
457 Status = gBS->HandleProtocol (\r
458 DeviceHandle,\r
459 &gEfiDevicePathProtocolGuid,\r
460 (VOID*)&DevicePath\r
461 );\r
462 if (EFI_ERROR (Status)) {\r
463 return Status;\r
464 }\r
465 TempDevicePath = DevicePath;\r
466\r
467 //\r
468 // Register Keyboard\r
469 //\r
470 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);\r
471\r
9dc08ec6 472 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
30541881
RN
473\r
474 //\r
475 // Register COM1\r
476 //\r
477 DevicePath = TempDevicePath;\r
478 gPnp16550ComPortDeviceNode.UID = 0;\r
479\r
480 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
481 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
482 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
483\r
484 //\r
485 // Print Device Path\r
486 //\r
77f47588 487 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
30541881
RN
488 if (DevPathStr != NULL) {\r
489 DEBUG((\r
490 EFI_D_INFO,\r
491 "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
492 __LINE__,\r
493 gPnp16550ComPortDeviceNode.UID + 1,\r
494 DevPathStr\r
495 ));\r
496 FreePool(DevPathStr);\r
497 }\r
498\r
9dc08ec6
RN
499 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
500 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
501 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
30541881
RN
502\r
503 //\r
504 // Register COM2\r
505 //\r
506 DevicePath = TempDevicePath;\r
507 gPnp16550ComPortDeviceNode.UID = 1;\r
508\r
509 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);\r
510 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
511 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
512\r
513 //\r
514 // Print Device Path\r
515 //\r
77f47588 516 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
30541881
RN
517 if (DevPathStr != NULL) {\r
518 DEBUG((\r
519 EFI_D_INFO,\r
520 "BdsPlatform.c+%d: COM%d DevPath: %s\n",\r
521 __LINE__,\r
522 gPnp16550ComPortDeviceNode.UID + 1,\r
523 DevPathStr\r
524 ));\r
525 FreePool(DevPathStr);\r
526 }\r
527\r
9dc08ec6
RN
528 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
529 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
530 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
30541881
RN
531\r
532 return EFI_SUCCESS;\r
533}\r
534\r
535EFI_STATUS\r
536GetGopDevicePath (\r
537 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,\r
538 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath\r
539 )\r
540{\r
541 UINTN Index;\r
542 EFI_STATUS Status;\r
543 EFI_HANDLE PciDeviceHandle;\r
544 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
545 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;\r
546 UINTN GopHandleCount;\r
547 EFI_HANDLE *GopHandleBuffer;\r
548\r
549 if (PciDevicePath == NULL || GopDevicePath == NULL) {\r
550 return EFI_INVALID_PARAMETER;\r
551 }\r
552\r
553 //\r
554 // Initialize the GopDevicePath to be PciDevicePath\r
555 //\r
556 *GopDevicePath = PciDevicePath;\r
557 TempPciDevicePath = PciDevicePath;\r
558\r
559 Status = gBS->LocateDevicePath (\r
560 &gEfiDevicePathProtocolGuid,\r
561 &TempPciDevicePath,\r
562 &PciDeviceHandle\r
563 );\r
564 if (EFI_ERROR (Status)) {\r
565 return Status;\r
566 }\r
567\r
568 //\r
569 // Try to connect this handle, so that GOP dirver could start on this\r
570 // device and create child handles with GraphicsOutput Protocol installed\r
571 // on them, then we get device paths of these child handles and select\r
572 // them as possible console device.\r
573 //\r
574 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);\r
575\r
576 Status = gBS->LocateHandleBuffer (\r
577 ByProtocol,\r
578 &gEfiGraphicsOutputProtocolGuid,\r
579 NULL,\r
580 &GopHandleCount,\r
581 &GopHandleBuffer\r
582 );\r
583 if (!EFI_ERROR (Status)) {\r
584 //\r
585 // Add all the child handles as possible Console Device\r
586 //\r
587 for (Index = 0; Index < GopHandleCount; Index++) {\r
588 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);\r
589 if (EFI_ERROR (Status)) {\r
590 continue;\r
591 }\r
592 if (CompareMem (\r
593 PciDevicePath,\r
594 TempDevicePath,\r
595 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH\r
596 ) == 0) {\r
597 //\r
598 // In current implementation, we only enable one of the child handles\r
599 // as console device, i.e. sotre one of the child handle's device\r
600 // path to variable "ConOut"\r
601 // In futhure, we could select all child handles to be console device\r
602 //\r
603\r
604 *GopDevicePath = TempDevicePath;\r
605\r
606 //\r
607 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()\r
608 // Add the integrity GOP device path.\r
609 //\r
9dc08ec6
RN
610 EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);\r
611 EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);\r
30541881
RN
612 }\r
613 }\r
614 gBS->FreePool (GopHandleBuffer);\r
615 }\r
616\r
617 return EFI_SUCCESS;\r
618}\r
619\r
620EFI_STATUS\r
4fdb585c 621PreparePciDisplayDevicePath (\r
30541881
RN
622 IN EFI_HANDLE DeviceHandle\r
623 )\r
624/*++\r
625\r
626Routine Description:\r
627\r
628 Add PCI VGA to ConOut.\r
629 PCI VGA: 03 00 00\r
630\r
631Arguments:\r
632\r
633 DeviceHandle - Handle of PCIIO protocol.\r
634\r
635Returns:\r
636\r
637 EFI_SUCCESS - PCI VGA is added to ConOut.\r
638 EFI_STATUS - No PCI VGA device is added.\r
639\r
640--*/\r
641{\r
642 EFI_STATUS Status;\r
643 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
644 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;\r
645\r
646 DevicePath = NULL;\r
647 GopDevicePath = NULL;\r
648 Status = gBS->HandleProtocol (\r
649 DeviceHandle,\r
650 &gEfiDevicePathProtocolGuid,\r
651 (VOID*)&DevicePath\r
652 );\r
653 if (EFI_ERROR (Status)) {\r
654 return Status;\r
655 }\r
656\r
657 GetGopDevicePath (DevicePath, &GopDevicePath);\r
658 DevicePath = GopDevicePath;\r
659\r
9dc08ec6 660 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
30541881
RN
661\r
662 return EFI_SUCCESS;\r
663}\r
664\r
665EFI_STATUS\r
666PreparePciSerialDevicePath (\r
667 IN EFI_HANDLE DeviceHandle\r
668 )\r
669/*++\r
670\r
671Routine Description:\r
672\r
673 Add PCI Serial to ConOut, ConIn, ErrOut.\r
674 PCI Serial: 07 00 02\r
675\r
676Arguments:\r
677\r
678 DeviceHandle - Handle of PCIIO protocol.\r
679\r
680Returns:\r
681\r
682 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.\r
683 EFI_STATUS - No PCI Serial device is added.\r
684\r
685--*/\r
686{\r
687 EFI_STATUS Status;\r
688 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
689\r
690 DevicePath = NULL;\r
691 Status = gBS->HandleProtocol (\r
692 DeviceHandle,\r
693 &gEfiDevicePathProtocolGuid,\r
694 (VOID*)&DevicePath\r
695 );\r
696 if (EFI_ERROR (Status)) {\r
697 return Status;\r
698 }\r
699\r
700 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);\r
701 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);\r
702\r
9dc08ec6
RN
703 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
704 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);\r
705 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
30541881
RN
706\r
707 return EFI_SUCCESS;\r
708}\r
709\r
710EFI_STATUS\r
711VisitAllInstancesOfProtocol (\r
712 IN EFI_GUID *Id,\r
713 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,\r
714 IN VOID *Context\r
715 )\r
716{\r
717 EFI_STATUS Status;\r
718 UINTN HandleCount;\r
719 EFI_HANDLE *HandleBuffer;\r
720 UINTN Index;\r
721 VOID *Instance;\r
722\r
723 //\r
724 // Start to check all the PciIo to find all possible device\r
725 //\r
726 HandleCount = 0;\r
727 HandleBuffer = NULL;\r
728 Status = gBS->LocateHandleBuffer (\r
729 ByProtocol,\r
730 Id,\r
731 NULL,\r
732 &HandleCount,\r
733 &HandleBuffer\r
734 );\r
735 if (EFI_ERROR (Status)) {\r
736 return Status;\r
737 }\r
738\r
739 for (Index = 0; Index < HandleCount; Index++) {\r
740 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);\r
741 if (EFI_ERROR (Status)) {\r
742 continue;\r
743 }\r
744\r
745 Status = (*CallBackFunction) (\r
746 HandleBuffer[Index],\r
747 Instance,\r
748 Context\r
749 );\r
750 }\r
751\r
752 gBS->FreePool (HandleBuffer);\r
753\r
754 return EFI_SUCCESS;\r
755}\r
756\r
757\r
758EFI_STATUS\r
759EFIAPI\r
760VisitingAPciInstance (\r
761 IN EFI_HANDLE Handle,\r
762 IN VOID *Instance,\r
763 IN VOID *Context\r
764 )\r
765{\r
766 EFI_STATUS Status;\r
767 EFI_PCI_IO_PROTOCOL *PciIo;\r
768 PCI_TYPE00 Pci;\r
769\r
770 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;\r
771\r
772 //\r
773 // Check for all PCI device\r
774 //\r
775 Status = PciIo->Pci.Read (\r
776 PciIo,\r
777 EfiPciIoWidthUint32,\r
778 0,\r
779 sizeof (Pci) / sizeof (UINT32),\r
780 &Pci\r
781 );\r
782 if (EFI_ERROR (Status)) {\r
783 return Status;\r
784 }\r
785\r
786 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (\r
787 Handle,\r
788 PciIo,\r
789 &Pci\r
790 );\r
791\r
792}\r
793\r
794\r
795\r
796EFI_STATUS\r
797VisitAllPciInstances (\r
798 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction\r
799 )\r
800{\r
801 return VisitAllInstancesOfProtocol (\r
802 &gEfiPciIoProtocolGuid,\r
803 VisitingAPciInstance,\r
804 (VOID*)(UINTN) CallBackFunction\r
805 );\r
806}\r
807\r
808\r
809/**\r
810 Do platform specific PCI Device check and add them to\r
811 ConOut, ConIn, ErrOut.\r
812\r
813 @param[in] Handle - Handle of PCI device instance\r
814 @param[in] PciIo - PCI IO protocol instance\r
815 @param[in] Pci - PCI Header register block\r
816\r
817 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
818 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
819\r
820**/\r
821EFI_STATUS\r
822EFIAPI\r
823DetectAndPreparePlatformPciDevicePath (\r
824 IN EFI_HANDLE Handle,\r
825 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
826 IN PCI_TYPE00 *Pci\r
827 )\r
828{\r
829 EFI_STATUS Status;\r
830\r
831 Status = PciIo->Attributes (\r
832 PciIo,\r
833 EfiPciIoAttributeOperationEnable,\r
834 EFI_PCI_DEVICE_ENABLE,\r
835 NULL\r
836 );\r
837 ASSERT_EFI_ERROR (Status);\r
838\r
839 if (!mDetectVgaOnly) {\r
840 //\r
841 // Here we decide whether it is LPC Bridge\r
842 //\r
843 if ((IS_PCI_LPC (Pci)) ||\r
844 ((IS_PCI_ISA_PDECODE (Pci)) &&\r
845 (Pci->Hdr.VendorId == 0x8086) &&\r
846 (Pci->Hdr.DeviceId == 0x7000)\r
847 )\r
848 ) {\r
849 //\r
850 // Add IsaKeyboard to ConIn,\r
851 // add IsaSerial to ConOut, ConIn, ErrOut\r
852 //\r
853 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));\r
854 PrepareLpcBridgeDevicePath (Handle);\r
855 return EFI_SUCCESS;\r
856 }\r
857 //\r
858 // Here we decide which Serial device to enable in PCI bus\r
859 //\r
860 if (IS_PCI_16550SERIAL (Pci)) {\r
861 //\r
862 // Add them to ConOut, ConIn, ErrOut.\r
863 //\r
864 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));\r
865 PreparePciSerialDevicePath (Handle);\r
866 return EFI_SUCCESS;\r
867 }\r
868 }\r
869\r
870 //\r
4fdb585c 871 // Here we decide which display device to enable in PCI bus\r
30541881 872 //\r
4fdb585c 873 if (IS_PCI_DISPLAY (Pci)) {\r
30541881
RN
874 //\r
875 // Add them to ConOut.\r
876 //\r
4fdb585c
LE
877 DEBUG ((EFI_D_INFO, "Found PCI display device\n"));\r
878 PreparePciDisplayDevicePath (Handle);\r
30541881
RN
879 return EFI_SUCCESS;\r
880 }\r
881\r
882 return Status;\r
883}\r
884\r
885\r
886/**\r
887 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
888\r
889 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.\r
890\r
891 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.\r
892 @retval EFI_STATUS - PCI Device check or Console variable update fail.\r
893\r
894**/\r
895EFI_STATUS\r
896DetectAndPreparePlatformPciDevicePaths (\r
897 BOOLEAN DetectVgaOnly\r
898 )\r
899{\r
900 mDetectVgaOnly = DetectVgaOnly;\r
901 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);\r
902}\r
903\r
904\r
e9e9ad64
RN
905VOID\r
906PlatformInitializeConsole (\r
907 IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole\r
30541881
RN
908 )\r
909/*++\r
910\r
911Routine Description:\r
912\r
913 Connect the predefined platform default console device. Always try to find\r
914 and enable the vga device if have.\r
915\r
916Arguments:\r
917\r
918 PlatformConsole - Predfined platform default console device array.\r
30541881
RN
919--*/\r
920{\r
30541881
RN
921 UINTN Index;\r
922 EFI_DEVICE_PATH_PROTOCOL *VarConout;\r
923 EFI_DEVICE_PATH_PROTOCOL *VarConin;\r
30541881
RN
924\r
925 //\r
926 // Connect RootBridge\r
927 //\r
e9e9ad64
RN
928 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);\r
929 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);\r
30541881
RN
930\r
931 if (VarConout == NULL || VarConin == NULL) {\r
932 //\r
933 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut\r
934 //\r
935 DetectAndPreparePlatformPciDevicePaths (FALSE);\r
936\r
937 //\r
938 // Have chance to connect the platform default console,\r
939 // the platform default console is the minimue device group\r
940 // the platform should support\r
941 //\r
942 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {\r
943 //\r
944 // Update the console variable with the connect type\r
945 //\r
946 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
9dc08ec6 947 EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);\r
30541881
RN
948 }\r
949 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
9dc08ec6 950 EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);\r
30541881
RN
951 }\r
952 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
9dc08ec6 953 EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);\r
30541881
RN
954 }\r
955 }\r
956 } else {\r
957 //\r
958 // Only detect VGA device and add them to ConOut\r
959 //\r
960 DetectAndPreparePlatformPciDevicePaths (TRUE);\r
961 }\r
30541881
RN
962}\r
963\r
964\r
965/**\r
966 Configure PCI Interrupt Line register for applicable devices\r
967 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()\r
968\r
969 @param[in] Handle - Handle of PCI device instance\r
970 @param[in] PciIo - PCI IO protocol instance\r
971 @param[in] PciHdr - PCI Header register block\r
972\r
973 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.\r
974\r
975**/\r
976EFI_STATUS\r
977EFIAPI\r
978SetPciIntLine (\r
979 IN EFI_HANDLE Handle,\r
980 IN EFI_PCI_IO_PROTOCOL *PciIo,\r
981 IN PCI_TYPE00 *PciHdr\r
982 )\r
983{\r
984 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
985 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
986 UINTN RootSlot;\r
987 UINTN Idx;\r
988 UINT8 IrqLine;\r
989 EFI_STATUS Status;\r
990 UINT32 RootBusNumber;\r
991\r
992 Status = EFI_SUCCESS;\r
993\r
994 if (PciHdr->Device.InterruptPin != 0) {\r
995\r
996 DevPathNode = DevicePathFromHandle (Handle);\r
997 ASSERT (DevPathNode != NULL);\r
998 DevPath = DevPathNode;\r
999\r
1000 RootBusNumber = 0;\r
1001 if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&\r
1002 DevicePathSubType (DevPathNode) == ACPI_DP &&\r
1003 ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {\r
1004 RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;\r
1005 }\r
1006\r
1007 //\r
1008 // Compute index into PciHostIrqs[] table by walking\r
1009 // the device path and adding up all device numbers\r
1010 //\r
1011 Status = EFI_NOT_FOUND;\r
1012 RootSlot = 0;\r
1013 Idx = PciHdr->Device.InterruptPin - 1;\r
1014 while (!IsDevicePathEnd (DevPathNode)) {\r
1015 if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&\r
1016 DevicePathSubType (DevPathNode) == HW_PCI_DP) {\r
1017\r
1018 Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
1019\r
1020 //\r
1021 // Unlike SeaBIOS, which starts climbing from the leaf device\r
1022 // up toward the root, we traverse the device path starting at\r
1023 // the root moving toward the leaf node.\r
1024 // The slot number of the top-level parent bridge is needed for\r
1025 // Q35 cases with more than 24 slots on the root bus.\r
1026 //\r
1027 if (Status != EFI_SUCCESS) {\r
1028 Status = EFI_SUCCESS;\r
1029 RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;\r
1030 }\r
1031 }\r
1032\r
1033 DevPathNode = NextDevicePathNode (DevPathNode);\r
1034 }\r
1035 if (EFI_ERROR (Status)) {\r
1036 return Status;\r
1037 }\r
1038 if (RootBusNumber == 0 && RootSlot == 0) {\r
1039 DEBUG((\r
1040 EFI_D_ERROR,\r
1041 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",\r
1042 __FUNCTION__\r
1043 ));\r
1044 ASSERT (FALSE);\r
1045 }\r
1046\r
1047 //\r
1048 // Final PciHostIrqs[] index calculation depends on the platform\r
1049 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()\r
1050 //\r
1051 switch (mHostBridgeDevId) {\r
1052 case INTEL_82441_DEVICE_ID:\r
1053 Idx -= 1;\r
1054 break;\r
1055 case INTEL_Q35_MCH_DEVICE_ID:\r
1056 //\r
1057 // SeaBIOS contains the following comment:\r
1058 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but\r
1059 // with a different starting index - see q35-acpi-dsdt.dsl.\r
1060 //\r
1061 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"\r
1062 //\r
1063 if (RootSlot > 24) {\r
1064 //\r
1065 // in this case, subtract back out RootSlot from Idx\r
1066 // (SeaBIOS never adds it to begin with, but that would make our\r
1067 // device path traversal loop above too awkward)\r
1068 //\r
1069 Idx -= RootSlot;\r
1070 }\r
1071 break;\r
1072 default:\r
1073 ASSERT (FALSE); // should never get here\r
1074 }\r
1075 Idx %= ARRAY_SIZE (PciHostIrqs);\r
1076 IrqLine = PciHostIrqs[Idx];\r
1077\r
1078 DEBUG_CODE_BEGIN ();\r
1079 {\r
1080 CHAR16 *DevPathString;\r
1081 STATIC CHAR16 Fallback[] = L"<failed to convert>";\r
1082 UINTN Segment, Bus, Device, Function;\r
1083\r
1084 DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);\r
1085 if (DevPathString == NULL) {\r
1086 DevPathString = Fallback;\r
1087 }\r
1088 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);\r
1089 ASSERT_EFI_ERROR (Status);\r
1090\r
1091 DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,\r
1092 (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,\r
1093 IrqLine));\r
1094\r
1095 if (DevPathString != Fallback) {\r
1096 FreePool (DevPathString);\r
1097 }\r
1098 }\r
1099 DEBUG_CODE_END ();\r
1100\r
1101 //\r
1102 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]\r
1103 //\r
1104 Status = PciIo->Pci.Write (\r
1105 PciIo,\r
1106 EfiPciIoWidthUint8,\r
1107 PCI_INT_LINE_OFFSET,\r
1108 1,\r
1109 &IrqLine\r
1110 );\r
1111 }\r
1112\r
1113 return Status;\r
1114}\r
1115\r
1116\r
1117VOID\r
1118PciAcpiInitialization (\r
1119 )\r
1120{\r
1121 UINTN Pmba;\r
1122\r
1123 //\r
1124 // Query Host Bridge DID to determine platform type\r
1125 //\r
1126 mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);\r
1127 switch (mHostBridgeDevId) {\r
1128 case INTEL_82441_DEVICE_ID:\r
1129 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);\r
1130 //\r
1131 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets\r
1132 //\r
1133 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A\r
1134 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B\r
1135 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C\r
1136 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D\r
1137 break;\r
1138 case INTEL_Q35_MCH_DEVICE_ID:\r
1139 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);\r
1140 //\r
1141 // 00:1f.0 LPC Bridge (Q35) LNK routing targets\r
1142 //\r
1143 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A\r
1144 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B\r
1145 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C\r
1146 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D\r
1147 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E\r
1148 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F\r
1149 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G\r
1150 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H\r
1151 break;\r
1152 default:\r
1153 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
1154 __FUNCTION__, mHostBridgeDevId));\r
1155 ASSERT (FALSE);\r
1156 return;\r
1157 }\r
1158\r
1159 //\r
1160 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices\r
1161 //\r
1162 VisitAllPciInstances (SetPciIntLine);\r
1163\r
1164 //\r
1165 // Set ACPI SCI_EN bit in PMCNTRL\r
1166 //\r
1167 IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);\r
1168}\r
1169\r
da2369d2
GL
1170/**\r
1171 This function detects if OVMF is running on Xen.\r
1172\r
1173**/\r
1174STATIC\r
1175BOOLEAN\r
1176XenDetected (\r
1177 VOID\r
1178 )\r
1179{\r
1180 EFI_HOB_GUID_TYPE *GuidHob;\r
1181 STATIC INTN FoundHob = -1;\r
1182\r
1183 if (FoundHob == 0) {\r
1184 return FALSE;\r
1185 } else if (FoundHob == 1) {\r
1186 return TRUE;\r
1187 }\r
1188\r
1189 //\r
1190 // See if a XenInfo HOB is available\r
1191 //\r
1192 GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);\r
1193 if (GuidHob == NULL) {\r
1194 FoundHob = 0;\r
1195 return FALSE;\r
1196 }\r
1197\r
1198 FoundHob = 1;\r
1199 return TRUE;\r
1200}\r
30541881
RN
1201\r
1202EFI_STATUS\r
1203EFIAPI\r
1204ConnectRecursivelyIfPciMassStorage (\r
1205 IN EFI_HANDLE Handle,\r
1206 IN EFI_PCI_IO_PROTOCOL *Instance,\r
1207 IN PCI_TYPE00 *PciHeader\r
1208 )\r
1209{\r
1210 EFI_STATUS Status;\r
1211 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1212 CHAR16 *DevPathStr;\r
1213\r
da2369d2
GL
1214 //\r
1215 // Recognize PCI Mass Storage, and Xen PCI devices\r
1216 //\r
1217 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ||\r
1218 (XenDetected() && IS_CLASS2 (PciHeader, 0xFF, 0x80))) {\r
30541881
RN
1219 DevicePath = NULL;\r
1220 Status = gBS->HandleProtocol (\r
1221 Handle,\r
1222 &gEfiDevicePathProtocolGuid,\r
1223 (VOID*)&DevicePath\r
1224 );\r
1225 if (EFI_ERROR (Status)) {\r
1226 return Status;\r
1227 }\r
1228\r
1229 //\r
1230 // Print Device Path\r
1231 //\r
77f47588 1232 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);\r
30541881
RN
1233 if (DevPathStr != NULL) {\r
1234 DEBUG((\r
1235 EFI_D_INFO,\r
da2369d2
GL
1236 "Found %s device: %s\n",\r
1237 IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ? L"Mass Storage" : L"Xen",\r
30541881
RN
1238 DevPathStr\r
1239 ));\r
1240 FreePool(DevPathStr);\r
1241 }\r
1242\r
1243 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
1244 if (EFI_ERROR (Status)) {\r
1245 return Status;\r
1246 }\r
1247\r
1248 }\r
1249\r
1250 return EFI_SUCCESS;\r
1251}\r
1252\r
1253\r
1254/**\r
1255 This notification function is invoked when the\r
1256 EMU Variable FVB has been changed.\r
1257\r
8c0b0b34
TH
1258 @param Event The event that occurred\r
1259 @param Context For EFI compatibility. Not used.\r
30541881
RN
1260\r
1261**/\r
1262VOID\r
1263EFIAPI\r
1264EmuVariablesUpdatedCallback (\r
1265 IN EFI_EVENT Event,\r
1266 IN VOID *Context\r
1267 )\r
1268{\r
1269 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));\r
1270 UpdateNvVarsOnFileSystem ();\r
1271}\r
1272\r
1273\r
1274EFI_STATUS\r
1275EFIAPI\r
1276VisitingFileSystemInstance (\r
1277 IN EFI_HANDLE Handle,\r
1278 IN VOID *Instance,\r
1279 IN VOID *Context\r
1280 )\r
1281{\r
1282 EFI_STATUS Status;\r
1283 STATIC BOOLEAN ConnectedToFileSystem = FALSE;\r
1284\r
1285 if (ConnectedToFileSystem) {\r
1286 return EFI_ALREADY_STARTED;\r
1287 }\r
1288\r
1289 Status = ConnectNvVarsToFileSystem (Handle);\r
1290 if (EFI_ERROR (Status)) {\r
1291 return Status;\r
1292 }\r
1293\r
1294 ConnectedToFileSystem = TRUE;\r
1295 mEmuVariableEvent =\r
1296 EfiCreateProtocolNotifyEvent (\r
1297 &gEfiDevicePathProtocolGuid,\r
1298 TPL_CALLBACK,\r
1299 EmuVariablesUpdatedCallback,\r
1300 NULL,\r
1301 &mEmuVariableEventReg\r
1302 );\r
1303 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);\r
1304\r
1305 return EFI_SUCCESS;\r
1306}\r
1307\r
1308\r
1309VOID\r
1310PlatformBdsRestoreNvVarsFromHardDisk (\r
1311 )\r
1312{\r
1313 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);\r
1314 VisitAllInstancesOfProtocol (\r
1315 &gEfiSimpleFileSystemProtocolGuid,\r
1316 VisitingFileSystemInstance,\r
1317 NULL\r
1318 );\r
1319\r
1320}\r
1321\r
30541881
RN
1322VOID\r
1323PlatformBdsConnectSequence (\r
1324 VOID\r
1325 )\r
1326/*++\r
1327\r
1328Routine Description:\r
1329\r
1330 Connect with predeined platform connect sequence,\r
1331 the OEM/IBV can customize with their own connect sequence.\r
1332\r
1333Arguments:\r
1334\r
1335 None.\r
1336\r
1337Returns:\r
1338\r
1339 None.\r
1340\r
1341--*/\r
1342{\r
1343 UINTN Index;\r
1344\r
1345 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));\r
1346\r
1347 Index = 0;\r
1348\r
1349 //\r
1350 // Here we can get the customized platform connect sequence\r
1351 // Notes: we can connect with new variable which record the\r
1352 // last time boots connect device path sequence\r
1353 //\r
1354 while (gPlatformConnectSequence[Index] != NULL) {\r
1355 //\r
1356 // Build the platform boot option\r
1357 //\r
fed691a6 1358 EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);\r
30541881
RN
1359 Index++;\r
1360 }\r
1361\r
1362 //\r
1363 // Just use the simple policy to connect all devices\r
1364 //\r
fed691a6
RN
1365 DEBUG ((EFI_D_INFO, "EfiBootManagerConnectAll\n"));\r
1366 EfiBootManagerConnectAll ();\r
30541881
RN
1367\r
1368 PciAcpiInitialization ();\r
30541881
RN
1369}\r
1370\r
30541881
RN
1371/**\r
1372 Save the S3 boot script.\r
1373\r
1374 Note that DxeSmmReadyToLock must be signaled after this function returns;\r
1375 otherwise the script wouldn't be saved actually.\r
1376**/\r
1377STATIC\r
1378VOID\r
1379SaveS3BootScript (\r
1380 VOID\r
1381 )\r
1382{\r
1383 EFI_STATUS Status;\r
1384 EFI_S3_SAVE_STATE_PROTOCOL *BootScript;\r
1385 STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };\r
1386\r
1387 Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,\r
1388 (VOID **) &BootScript);\r
1389 ASSERT_EFI_ERROR (Status);\r
1390\r
1391 //\r
1392 // Despite the opcode documentation in the PI spec, the protocol\r
1393 // implementation embeds a deep copy of the info in the boot script, rather\r
1394 // than storing just a pointer to runtime or NVS storage.\r
1395 //\r
1396 Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,\r
1397 (UINT32) sizeof Info,\r
1398 (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);\r
1399 ASSERT_EFI_ERROR (Status);\r
1400}\r
1401\r
1402\r
1403VOID\r
1404EFIAPI\r
a7566234
RN
1405PlatformBootManagerAfterConsole (\r
1406 VOID\r
30541881
RN
1407 )\r
1408/*++\r
1409\r
1410Routine Description:\r
1411\r
1412 The function will excute with as the platform policy, current policy\r
1413 is driven by boot mode. IBV/OEM can customize this code for their specific\r
1414 policy action.\r
1415\r
30541881
RN
1416--*/\r
1417{\r
30541881
RN
1418 EFI_BOOT_MODE BootMode;\r
1419\r
a7566234 1420 DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));\r
30541881
RN
1421\r
1422 if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {\r
1423 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "\r
1424 "from disk since flash variables appear to be supported.\n"));\r
1425 } else {\r
1426 //\r
1427 // Try to restore variables from the hard disk early so\r
1428 // they can be used for the other BDS connect operations.\r
1429 //\r
1430 PlatformBdsRestoreNvVarsFromHardDisk ();\r
1431 }\r
1432\r
30541881
RN
1433 //\r
1434 // Get current Boot Mode\r
1435 //\r
30edcbf5 1436 BootMode = GetBootModeHob ();\r
30541881
RN
1437 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));\r
1438\r
1439 //\r
1440 // Go the different platform policy with different boot mode\r
1441 // Notes: this part code can be change with the table policy\r
1442 //\r
1443 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);\r
30541881
RN
1444\r
1445 //\r
e64a2ebe 1446 // Logo show\r
30541881 1447 //\r
ab970515 1448 BootLogoEnableLogo ();\r
30541881
RN
1449\r
1450 //\r
1451 // Perform some platform specific connect sequence\r
1452 //\r
1453 PlatformBdsConnectSequence ();\r
1454\r
1455 //\r
1456 // Process QEMU's -kernel command line option\r
1457 //\r
1458 TryRunningQemuKernel ();\r
30541881 1459\r
04fe914b
RN
1460 EfiBootManagerRefreshAllBootOption ();\r
1461\r
14b2ebc3
GL
1462 //\r
1463 // Register UEFI Shell\r
1464 //\r
1465 PlatformRegisterFvBootOption (\r
1466 PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE\r
1467 );\r
1468\r
2eb35898 1469 RemoveStaleFvFileOptions ();\r
2542feea 1470 SetBootOrderFromQemu ();\r
30541881
RN
1471}\r
1472\r
30541881
RN
1473/**\r
1474 This notification function is invoked when an instance of the\r
1475 EFI_DEVICE_PATH_PROTOCOL is produced.\r
1476\r
8c0b0b34
TH
1477 @param Event The event that occurred\r
1478 @param Context For EFI compatibility. Not used.\r
30541881
RN
1479\r
1480**/\r
1481VOID\r
1482EFIAPI\r
1483NotifyDevPath (\r
1484 IN EFI_EVENT Event,\r
1485 IN VOID *Context\r
1486 )\r
1487{\r
1488 EFI_HANDLE Handle;\r
1489 EFI_STATUS Status;\r
1490 UINTN BufferSize;\r
1491 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
1492 ATAPI_DEVICE_PATH *Atapi;\r
1493\r
1494 //\r
1495 // Examine all new handles\r
1496 //\r
1497 for (;;) {\r
1498 //\r
1499 // Get the next handle\r
1500 //\r
1501 BufferSize = sizeof (Handle);\r
1502 Status = gBS->LocateHandle (\r
1503 ByRegisterNotify,\r
1504 NULL,\r
1505 mEfiDevPathNotifyReg,\r
1506 &BufferSize,\r
1507 &Handle\r
1508 );\r
1509\r
1510 //\r
1511 // If not found, we're done\r
1512 //\r
1513 if (EFI_NOT_FOUND == Status) {\r
1514 break;\r
1515 }\r
1516\r
1517 if (EFI_ERROR (Status)) {\r
1518 continue;\r
1519 }\r
1520\r
1521 //\r
1522 // Get the DevicePath protocol on that handle\r
1523 //\r
1524 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);\r
1525 ASSERT_EFI_ERROR (Status);\r
1526\r
1527 while (!IsDevicePathEnd (DevPathNode)) {\r
1528 //\r
1529 // Find the handler to dump this device path node\r
1530 //\r
1531 if (\r
1532 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
1533 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
1534 ) {\r
1535 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
1536 PciOr16 (\r
1537 PCI_LIB_ADDRESS (\r
1538 0,\r
1539 1,\r
1540 1,\r
1541 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
1542 ),\r
1543 BIT15\r
1544 );\r
1545 }\r
1546\r
1547 //\r
1548 // Next device path node\r
1549 //\r
1550 DevPathNode = NextDevicePathNode (DevPathNode);\r
1551 }\r
1552 }\r
1553\r
1554 return;\r
1555}\r
1556\r
1557\r
1558VOID\r
1559InstallDevicePathCallback (\r
1560 VOID\r
1561 )\r
1562{\r
1563 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));\r
1564 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
1565 &gEfiDevicePathProtocolGuid,\r
1566 TPL_CALLBACK,\r
1567 NotifyDevPath,\r
1568 NULL,\r
1569 &mEfiDevPathNotifyReg\r
1570 );\r
1571}\r
1572\r
a7566234
RN
1573/**\r
1574 This function is called each second during the boot manager waits the timeout.\r
1575\r
1576 @param TimeoutRemain The remaining timeout.\r
1577**/\r
1578VOID\r
1579EFIAPI\r
1580PlatformBootManagerWaitCallback (\r
1581 UINT16 TimeoutRemain\r
1582 )\r
1583{\r
fd096a99
LE
1584 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
1585 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
1586 UINT16 Timeout;\r
1587\r
1588 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
1589\r
1590 Black.Raw = 0x00000000;\r
1591 White.Raw = 0x00FFFFFF;\r
1592\r
1593 BootLogoUpdateProgress (\r
1594 White.Pixel,\r
1595 Black.Pixel,\r
1596 L"Start boot option",\r
1597 White.Pixel,\r
1598 (Timeout - TimeoutRemain) * 100 / Timeout,\r
1599 0\r
1600 );\r
a7566234
RN
1601}\r
1602\r