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