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