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