]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
OvmfPkg/PlatformBootManagerLib: Register boot options and hot keys
[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
1405VOID\r
1406EFIAPI\r
1407PlatformBdsBootSuccess (\r
1408 IN BDS_COMMON_OPTION *Option\r
1409 )\r
1410/*++\r
1411\r
1412Routine Description:\r
1413\r
1414 Hook point after a boot attempt succeeds. We don't expect a boot option to\r
1415 return, so the EFI 1.0 specification defines that you will default to an\r
1416 interactive mode and stop processing the BootOrder list in this case. This\r
1417 is alos a platform implementation and can be customized by IBV/OEM.\r
1418\r
1419Arguments:\r
1420\r
1421 Option - Pointer to Boot Option that succeeded to boot.\r
1422\r
1423Returns:\r
1424\r
1425 None.\r
1426\r
1427--*/\r
1428{\r
1429 CHAR16 *TmpStr;\r
1430\r
1431 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));\r
1432 //\r
1433 // If Boot returned with EFI_SUCCESS and there is not in the boot device\r
1434 // select loop then we need to pop up a UI and wait for user input.\r
1435 //\r
1436 TmpStr = Option->StatusString;\r
1437 if (TmpStr != NULL) {\r
1438 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1439 FreePool (TmpStr);\r
1440 }\r
1441}\r
1442\r
1443VOID\r
1444EFIAPI\r
1445PlatformBdsBootFail (\r
1446 IN BDS_COMMON_OPTION *Option,\r
1447 IN EFI_STATUS Status,\r
1448 IN CHAR16 *ExitData,\r
1449 IN UINTN ExitDataSize\r
1450 )\r
1451/*++\r
1452\r
1453Routine Description:\r
1454\r
1455 Hook point after a boot attempt fails.\r
1456\r
1457Arguments:\r
1458\r
1459 Option - Pointer to Boot Option that failed to boot.\r
1460\r
1461 Status - Status returned from failed boot.\r
1462\r
1463 ExitData - Exit data returned from failed boot.\r
1464\r
1465 ExitDataSize - Exit data size returned from failed boot.\r
1466\r
1467Returns:\r
1468\r
1469 None.\r
1470\r
1471--*/\r
1472{\r
1473 CHAR16 *TmpStr;\r
1474\r
1475 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));\r
1476\r
1477 //\r
1478 // If Boot returned with failed status then we need to pop up a UI and wait\r
1479 // for user input.\r
1480 //\r
1481 TmpStr = Option->StatusString;\r
1482 if (TmpStr != NULL) {\r
1483 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);\r
1484 FreePool (TmpStr);\r
1485 }\r
1486}\r
1487\r
30541881
RN
1488VOID\r
1489EFIAPI\r
1490PlatformBdsLockNonUpdatableFlash (\r
1491 VOID\r
1492 )\r
1493{\r
1494 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));\r
1495 return;\r
1496}\r
1497\r
1498\r
1499/**\r
1500 This notification function is invoked when an instance of the\r
1501 EFI_DEVICE_PATH_PROTOCOL is produced.\r
1502\r
1503 @param Event The event that occured\r
1504 @param Context For EFI compatiblity. Not used.\r
1505\r
1506**/\r
1507VOID\r
1508EFIAPI\r
1509NotifyDevPath (\r
1510 IN EFI_EVENT Event,\r
1511 IN VOID *Context\r
1512 )\r
1513{\r
1514 EFI_HANDLE Handle;\r
1515 EFI_STATUS Status;\r
1516 UINTN BufferSize;\r
1517 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
1518 ATAPI_DEVICE_PATH *Atapi;\r
1519\r
1520 //\r
1521 // Examine all new handles\r
1522 //\r
1523 for (;;) {\r
1524 //\r
1525 // Get the next handle\r
1526 //\r
1527 BufferSize = sizeof (Handle);\r
1528 Status = gBS->LocateHandle (\r
1529 ByRegisterNotify,\r
1530 NULL,\r
1531 mEfiDevPathNotifyReg,\r
1532 &BufferSize,\r
1533 &Handle\r
1534 );\r
1535\r
1536 //\r
1537 // If not found, we're done\r
1538 //\r
1539 if (EFI_NOT_FOUND == Status) {\r
1540 break;\r
1541 }\r
1542\r
1543 if (EFI_ERROR (Status)) {\r
1544 continue;\r
1545 }\r
1546\r
1547 //\r
1548 // Get the DevicePath protocol on that handle\r
1549 //\r
1550 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);\r
1551 ASSERT_EFI_ERROR (Status);\r
1552\r
1553 while (!IsDevicePathEnd (DevPathNode)) {\r
1554 //\r
1555 // Find the handler to dump this device path node\r
1556 //\r
1557 if (\r
1558 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&\r
1559 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)\r
1560 ) {\r
1561 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;\r
1562 PciOr16 (\r
1563 PCI_LIB_ADDRESS (\r
1564 0,\r
1565 1,\r
1566 1,\r
1567 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40\r
1568 ),\r
1569 BIT15\r
1570 );\r
1571 }\r
1572\r
1573 //\r
1574 // Next device path node\r
1575 //\r
1576 DevPathNode = NextDevicePathNode (DevPathNode);\r
1577 }\r
1578 }\r
1579\r
1580 return;\r
1581}\r
1582\r
1583\r
1584VOID\r
1585InstallDevicePathCallback (\r
1586 VOID\r
1587 )\r
1588{\r
1589 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));\r
1590 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (\r
1591 &gEfiDevicePathProtocolGuid,\r
1592 TPL_CALLBACK,\r
1593 NotifyDevPath,\r
1594 NULL,\r
1595 &mEfiDevPathNotifyReg\r
1596 );\r
1597}\r
1598\r
a7566234
RN
1599/**\r
1600 This function is called each second during the boot manager waits the timeout.\r
1601\r
1602 @param TimeoutRemain The remaining timeout.\r
1603**/\r
1604VOID\r
1605EFIAPI\r
1606PlatformBootManagerWaitCallback (\r
1607 UINT16 TimeoutRemain\r
1608 )\r
1609{\r
1610}\r
1611\r