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