Home | History | Annotate | Download | only in PlatformIntelBdsLib
      1 /** @file
      2   Implementation for PlatformBdsLib library class interfaces.
      3 
      4   Copyright (C) 2015, Red Hat, Inc.
      5   Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>
      6   Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
      7 
      8   This program and the accompanying materials are licensed and made available
      9   under the terms and conditions of the BSD License which accompanies this
     10   distribution. The full text of the license may be found at
     11   http://opensource.org/licenses/bsd-license.php
     12 
     13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
     14   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     15 
     16 **/
     17 
     18 #include <IndustryStandard/Pci22.h>
     19 #include <Library/DevicePathLib.h>
     20 #include <Library/PcdLib.h>
     21 #include <Library/PlatformBdsLib.h>
     22 #include <Library/QemuBootOrderLib.h>
     23 #include <Protocol/DevicePath.h>
     24 #include <Protocol/GraphicsOutput.h>
     25 #include <Protocol/PciIo.h>
     26 #include <Protocol/PciRootBridgeIo.h>
     27 #include <Guid/EventGroup.h>
     28 
     29 #include "IntelBdsPlatform.h"
     30 
     31 #define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }
     32 
     33 
     34 #pragma pack (1)
     35 typedef struct {
     36   VENDOR_DEVICE_PATH         SerialDxe;
     37   UART_DEVICE_PATH           Uart;
     38   VENDOR_DEFINED_DEVICE_PATH TermType;
     39   EFI_DEVICE_PATH_PROTOCOL   End;
     40 } PLATFORM_SERIAL_CONSOLE;
     41 #pragma pack ()
     42 
     43 #define SERIAL_DXE_FILE_GUID { \
     44           0xD3987D4B, 0x971A, 0x435F, \
     45           { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \
     46           }
     47 
     48 STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {
     49   //
     50   // VENDOR_DEVICE_PATH SerialDxe
     51   //
     52   {
     53     { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },
     54     SERIAL_DXE_FILE_GUID
     55   },
     56 
     57   //
     58   // UART_DEVICE_PATH Uart
     59   //
     60   {
     61     { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },
     62     0,                                      // Reserved
     63     FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
     64     FixedPcdGet8 (PcdUartDefaultDataBits),  // DataBits
     65     FixedPcdGet8 (PcdUartDefaultParity),    // Parity
     66     FixedPcdGet8 (PcdUartDefaultStopBits)   // StopBits
     67   },
     68 
     69   //
     70   // VENDOR_DEFINED_DEVICE_PATH TermType
     71   //
     72   {
     73     {
     74       MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,
     75       DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)
     76     }
     77     //
     78     // Guid to be filled in dynamically
     79     //
     80   },
     81 
     82   //
     83   // EFI_DEVICE_PATH_PROTOCOL End
     84   //
     85   {
     86     END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
     87     DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
     88   }
     89 };
     90 
     91 
     92 #pragma pack (1)
     93 typedef struct {
     94   USB_CLASS_DEVICE_PATH    Keyboard;
     95   EFI_DEVICE_PATH_PROTOCOL End;
     96 } PLATFORM_USB_KEYBOARD;
     97 #pragma pack ()
     98 
     99 STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {
    100   //
    101   // USB_CLASS_DEVICE_PATH Keyboard
    102   //
    103   {
    104     {
    105       MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,
    106       DP_NODE_LEN (USB_CLASS_DEVICE_PATH)
    107     },
    108     0xFFFF, // VendorId: any
    109     0xFFFF, // ProductId: any
    110     3,      // DeviceClass: HID
    111     1,      // DeviceSubClass: boot
    112     1       // DeviceProtocol: keyboard
    113   },
    114 
    115   //
    116   // EFI_DEVICE_PATH_PROTOCOL End
    117   //
    118   {
    119     END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,
    120     DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)
    121   }
    122 };
    123 
    124 /**
    125   An empty function to pass error checking of CreateEventEx ().
    126 
    127   @param  Event                 Event whose notification function is being invoked.
    128   @param  Context               Pointer to the notification function's context,
    129                                 which is implementation-dependent.
    130 
    131 **/
    132 STATIC
    133 VOID
    134 EFIAPI
    135 EmptyCallbackFunction (
    136   IN EFI_EVENT                Event,
    137   IN VOID                     *Context
    138   )
    139 {
    140 }
    141 
    142 //
    143 // BDS Platform Functions
    144 //
    145 /**
    146   Platform Bds init. Include the platform firmware vendor, revision
    147   and so crc check.
    148 
    149 **/
    150 VOID
    151 EFIAPI
    152 PlatformBdsInit (
    153   VOID
    154   )
    155 {
    156   EFI_EVENT           EndOfDxeEvent;
    157   EFI_STATUS          Status;
    158 
    159   //
    160   // Signal EndOfDxe PI Event
    161   //
    162   Status = gBS->CreateEventEx (
    163                   EVT_NOTIFY_SIGNAL,
    164                   TPL_CALLBACK,
    165                   EmptyCallbackFunction,
    166                   NULL,
    167                   &gEfiEndOfDxeEventGroupGuid,
    168                   &EndOfDxeEvent
    169                   );
    170   if (!EFI_ERROR (Status)) {
    171     gBS->SignalEvent (EndOfDxeEvent);
    172     gBS->CloseEvent (EndOfDxeEvent);
    173   }
    174 }
    175 
    176 
    177 /**
    178   Check if the handle satisfies a particular condition.
    179 
    180   @param[in] Handle      The handle to check.
    181   @param[in] ReportText  A caller-allocated string passed in for reporting
    182                          purposes. It must never be NULL.
    183 
    184   @retval TRUE   The condition is satisfied.
    185   @retval FALSE  Otherwise. This includes the case when the condition could not
    186                  be fully evaluated due to an error.
    187 **/
    188 typedef
    189 BOOLEAN
    190 (EFIAPI *FILTER_FUNCTION) (
    191   IN EFI_HANDLE   Handle,
    192   IN CONST CHAR16 *ReportText
    193   );
    194 
    195 
    196 /**
    197   Process a handle.
    198 
    199   @param[in] Handle      The handle to process.
    200   @param[in] ReportText  A caller-allocated string passed in for reporting
    201                          purposes. It must never be NULL.
    202 **/
    203 typedef
    204 VOID
    205 (EFIAPI *CALLBACK_FUNCTION)  (
    206   IN EFI_HANDLE   Handle,
    207   IN CONST CHAR16 *ReportText
    208   );
    209 
    210 /**
    211   Locate all handles that carry the specified protocol, filter them with a
    212   callback function, and pass each handle that passes the filter to another
    213   callback.
    214 
    215   @param[in] ProtocolGuid  The protocol to look for.
    216 
    217   @param[in] Filter        The filter function to pass each handle to. If this
    218                            parameter is NULL, then all handles are processed.
    219 
    220   @param[in] Process       The callback function to pass each handle to that
    221                            clears the filter.
    222 **/
    223 STATIC
    224 VOID
    225 FilterAndProcess (
    226   IN EFI_GUID          *ProtocolGuid,
    227   IN FILTER_FUNCTION   Filter         OPTIONAL,
    228   IN CALLBACK_FUNCTION Process
    229   )
    230 {
    231   EFI_STATUS Status;
    232   EFI_HANDLE *Handles;
    233   UINTN      NoHandles;
    234   UINTN      Idx;
    235 
    236   Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,
    237                   NULL /* SearchKey */, &NoHandles, &Handles);
    238   if (EFI_ERROR (Status)) {
    239     //
    240     // This is not an error, just an informative condition.
    241     //
    242     DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,
    243       Status));
    244     return;
    245   }
    246 
    247   ASSERT (NoHandles > 0);
    248   for (Idx = 0; Idx < NoHandles; ++Idx) {
    249     CHAR16        *DevicePathText;
    250     STATIC CHAR16 Fallback[] = L"<device path unavailable>";
    251 
    252     //
    253     // The ConvertDevicePathToText() function handles NULL input transparently.
    254     //
    255     DevicePathText = ConvertDevicePathToText (
    256                        DevicePathFromHandle (Handles[Idx]),
    257                        FALSE, // DisplayOnly
    258                        FALSE  // AllowShortcuts
    259                        );
    260     if (DevicePathText == NULL) {
    261       DevicePathText = Fallback;
    262     }
    263 
    264     if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {
    265       Process (Handles[Idx], DevicePathText);
    266     }
    267 
    268     if (DevicePathText != Fallback) {
    269       FreePool (DevicePathText);
    270     }
    271   }
    272   gBS->FreePool (Handles);
    273 }
    274 
    275 
    276 /**
    277   This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.
    278 **/
    279 STATIC
    280 BOOLEAN
    281 EFIAPI
    282 IsPciDisplay (
    283   IN EFI_HANDLE   Handle,
    284   IN CONST CHAR16 *ReportText
    285   )
    286 {
    287   EFI_STATUS          Status;
    288   EFI_PCI_IO_PROTOCOL *PciIo;
    289   PCI_TYPE00          Pci;
    290 
    291   Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,
    292                   (VOID**)&PciIo);
    293   if (EFI_ERROR (Status)) {
    294     //
    295     // This is not an error worth reporting.
    296     //
    297     return FALSE;
    298   }
    299 
    300   Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,
    301                         sizeof Pci / sizeof (UINT32), &Pci);
    302   if (EFI_ERROR (Status)) {
    303     DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));
    304     return FALSE;
    305   }
    306 
    307   return IS_PCI_DISPLAY (&Pci);
    308 }
    309 
    310 
    311 /**
    312   This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking
    313   the matching driver to produce all first-level child handles.
    314 **/
    315 STATIC
    316 VOID
    317 EFIAPI
    318 Connect (
    319   IN EFI_HANDLE   Handle,
    320   IN CONST CHAR16 *ReportText
    321   )
    322 {
    323   EFI_STATUS Status;
    324 
    325   Status = gBS->ConnectController (
    326                   Handle, // ControllerHandle
    327                   NULL,   // DriverImageHandle
    328                   NULL,   // RemainingDevicePath -- produce all children
    329                   FALSE   // Recursive
    330                   );
    331   DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",
    332     __FUNCTION__, ReportText, Status));
    333 }
    334 
    335 
    336 /**
    337   This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the
    338   handle, and adds it to ConOut and ErrOut.
    339 **/
    340 STATIC
    341 VOID
    342 EFIAPI
    343 AddOutput (
    344   IN EFI_HANDLE   Handle,
    345   IN CONST CHAR16 *ReportText
    346   )
    347 {
    348   EFI_STATUS               Status;
    349   EFI_DEVICE_PATH_PROTOCOL *DevicePath;
    350 
    351   DevicePath = DevicePathFromHandle (Handle);
    352   if (DevicePath == NULL) {
    353     DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",
    354       __FUNCTION__, ReportText, Handle));
    355     return;
    356   }
    357 
    358   Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL);
    359   if (EFI_ERROR (Status)) {
    360     DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,
    361       ReportText, Status));
    362     return;
    363   }
    364 
    365   Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL);
    366   if (EFI_ERROR (Status)) {
    367     DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,
    368       ReportText, Status));
    369     return;
    370   }
    371 
    372   DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,
    373     ReportText));
    374 }
    375 
    376 
    377 /**
    378   The function will execute with as the platform policy, current policy
    379   is driven by boot mode. IBV/OEM can customize this code for their specific
    380   policy action.
    381 
    382   @param  DriverOptionList        The header of the driver option link list
    383   @param  BootOptionList          The header of the boot option link list
    384   @param  ProcessCapsules         A pointer to ProcessCapsules()
    385   @param  BaseMemoryTest          A pointer to BaseMemoryTest()
    386 
    387 **/
    388 VOID
    389 EFIAPI
    390 PlatformBdsPolicyBehavior (
    391   IN LIST_ENTRY                      *DriverOptionList,
    392   IN LIST_ENTRY                      *BootOptionList,
    393   IN PROCESS_CAPSULES                ProcessCapsules,
    394   IN BASEM_MEMORY_TEST               BaseMemoryTest
    395   )
    396 {
    397   //
    398   // Locate the PCI root bridges and make the PCI bus driver connect each,
    399   // non-recursively. This will produce a number of child handles with PciIo on
    400   // them.
    401   //
    402   FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);
    403 
    404   //
    405   // Find all display class PCI devices (using the handles from the previous
    406   // step), and connect them non-recursively. This should produce a number of
    407   // child handles with GOPs on them.
    408   //
    409   FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);
    410 
    411   //
    412   // Now add the device path of all handles with GOP on them to ConOut and
    413   // ErrOut.
    414   //
    415   FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);
    416 
    417   //
    418   // Add the hardcoded short-form USB keyboard device path to ConIn.
    419   //
    420   BdsLibUpdateConsoleVariable (L"ConIn",
    421     (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);
    422 
    423   //
    424   // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.
    425   //
    426   CopyGuid (&mSerialConsole.TermType.Guid,
    427     PcdGetPtr (PcdTerminalTypeGuidBuffer));
    428   BdsLibUpdateConsoleVariable (L"ConIn",
    429     (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
    430   BdsLibUpdateConsoleVariable (L"ConOut",
    431     (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
    432   BdsLibUpdateConsoleVariable (L"ErrOut",
    433     (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);
    434 
    435   //
    436   // Connect the consoles based on the above variables.
    437   //
    438   BdsLibConnectAllDefaultConsoles ();
    439 
    440   //
    441   // Show the splash screen.
    442   //
    443   EnableQuietBoot (PcdGetPtr (PcdLogoFile));
    444 
    445   //
    446   // Connect the rest of the devices.
    447   //
    448   BdsLibConnectAll ();
    449 
    450   //
    451   // Process QEMU's -kernel command line option. Note that the kernel booted
    452   // this way should receive ACPI tables, which is why we connect all devices
    453   // first (see above) -- PCI enumeration blocks ACPI table installation, if
    454   // there is a PCI host.
    455   //
    456   TryRunningQemuKernel ();
    457 
    458   BdsLibEnumerateAllBootOption (BootOptionList);
    459   SetBootOrderFromQemu (BootOptionList);
    460   //
    461   // The BootOrder variable may have changed, reload the in-memory list with
    462   // it.
    463   //
    464   BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
    465 
    466   PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);
    467 }
    468 
    469 /**
    470   Hook point after a boot attempt succeeds. We don't expect a boot option to
    471   return, so the UEFI 2.0 specification defines that you will default to an
    472   interactive mode and stop processing the BootOrder list in this case. This
    473   is also a platform implementation and can be customized by IBV/OEM.
    474 
    475   @param  Option                  Pointer to Boot Option that succeeded to boot.
    476 
    477 **/
    478 VOID
    479 EFIAPI
    480 PlatformBdsBootSuccess (
    481   IN  BDS_COMMON_OPTION *Option
    482   )
    483 {
    484 }
    485 
    486 /**
    487   Hook point after a boot attempt fails.
    488 
    489   @param  Option                  Pointer to Boot Option that failed to boot.
    490   @param  Status                  Status returned from failed boot.
    491   @param  ExitData                Exit data returned from failed boot.
    492   @param  ExitDataSize            Exit data size returned from failed boot.
    493 
    494 **/
    495 VOID
    496 EFIAPI
    497 PlatformBdsBootFail (
    498   IN  BDS_COMMON_OPTION  *Option,
    499   IN  EFI_STATUS         Status,
    500   IN  CHAR16             *ExitData,
    501   IN  UINTN              ExitDataSize
    502   )
    503 {
    504 }
    505 
    506 /**
    507   This function locks platform flash that is not allowed to be updated during normal boot path.
    508   The flash layout is platform specific.
    509 **/
    510 VOID
    511 EFIAPI
    512 PlatformBdsLockNonUpdatableFlash (
    513   VOID
    514   )
    515 {
    516   return;
    517 }
    518