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