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