https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			282 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  This module produces Boot Manager Policy protocol.
 | 
						|
 | 
						|
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <Uefi.h>
 | 
						|
#include <Protocol/BootManagerPolicy.h>
 | 
						|
#include <Protocol/ManagedNetwork.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/UefiLib.h>
 | 
						|
#include <Library/DevicePathLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/UefiRuntimeServicesTableLib.h>
 | 
						|
#include <Library/UefiBootManagerLib.h>
 | 
						|
 | 
						|
CHAR16 mNetworkDeviceList[] = L"_NDL";
 | 
						|
 | 
						|
/**
 | 
						|
  Connect all the system drivers to controllers and create the network device list in NV storage.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS      Network devices are connected.
 | 
						|
  @retval EFI_DEVICE_ERROR No network device is connected.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ConnectAllAndCreateNetworkDeviceList (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_HANDLE                      *Handles;
 | 
						|
  UINTN                           HandleCount;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL        *SingleDevice;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL        *Devices;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
 | 
						|
 | 
						|
  EfiBootManagerConnectAll ();
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiManagedNetworkServiceBindingProtocolGuid, NULL, &HandleCount, &Handles);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    Handles = NULL;
 | 
						|
    HandleCount = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  Devices = NULL;
 | 
						|
  while (HandleCount-- != 0) {
 | 
						|
    Status = gBS->HandleProtocol (Handles[HandleCount], &gEfiDevicePathProtocolGuid, (VOID **) &SingleDevice);
 | 
						|
    if (EFI_ERROR (Status) || (SingleDevice == NULL)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    TempDevicePath = Devices;
 | 
						|
    Devices = AppendDevicePathInstance (Devices, SingleDevice);
 | 
						|
    if (TempDevicePath != NULL) {
 | 
						|
      FreePool (TempDevicePath);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Devices != NULL) {
 | 
						|
    Status = gRT->SetVariable (
 | 
						|
                    mNetworkDeviceList,
 | 
						|
                    &gEfiCallerIdGuid,
 | 
						|
                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | 
						|
                    GetDevicePathSize (Devices),
 | 
						|
                    Devices
 | 
						|
                    );
 | 
						|
    //
 | 
						|
    // Fails to save the network device list to NV storage is not a fatal error.
 | 
						|
    // Only impact is performance.
 | 
						|
    //
 | 
						|
    FreePool (Devices);
 | 
						|
  }
 | 
						|
 | 
						|
  return (Devices == NULL) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Connect the network devices.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS      At least one network device was connected.
 | 
						|
  @retval EFI_DEVICE_ERROR Network devices were not connected due to an error.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
ConnectNetwork (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  BOOLEAN                       OneConnected;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *Devices;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *SingleDevice;
 | 
						|
  UINTN                         Size;
 | 
						|
 | 
						|
  OneConnected = FALSE;
 | 
						|
  GetVariable2 (mNetworkDeviceList, &gEfiCallerIdGuid, (VOID **) &Devices, NULL);
 | 
						|
  TempDevicePath = Devices;
 | 
						|
  while (TempDevicePath != NULL) {
 | 
						|
    SingleDevice = GetNextDevicePathInstance (&TempDevicePath, &Size);
 | 
						|
    Status = EfiBootManagerConnectDevicePath (SingleDevice, NULL);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      OneConnected = TRUE;
 | 
						|
    }
 | 
						|
    FreePool (SingleDevice);
 | 
						|
  }
 | 
						|
  if (Devices != NULL) {
 | 
						|
    FreePool (Devices);
 | 
						|
  }
 | 
						|
 | 
						|
  if (OneConnected) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Cached network devices list doesn't exist or is NOT valid.
 | 
						|
    //
 | 
						|
    return ConnectAllAndCreateNetworkDeviceList ();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Connect a device path following the platforms EFI Boot Manager policy.
 | 
						|
 | 
						|
  The ConnectDevicePath() function allows the caller to connect a DevicePath using the
 | 
						|
  same policy as the EFI Boot Manger.
 | 
						|
 | 
						|
  @param[in] This       A pointer to the EFI_BOOT_MANAGER_POLICY_PROTOCOL instance.
 | 
						|
  @param[in] DevicePath Points to the start of the EFI device path to connect.
 | 
						|
                        If DevicePath is NULL then all the controllers in the
 | 
						|
                        system will be connected using the platforms EFI Boot
 | 
						|
                        Manager policy.
 | 
						|
  @param[in] Recursive  If TRUE, then ConnectController() is called recursively
 | 
						|
                        until the entire tree of controllers below the
 | 
						|
                        controller specified by DevicePath have been created.
 | 
						|
                        If FALSE, then the tree of controllers is only expanded
 | 
						|
                        one level. If DevicePath is NULL then Recursive is ignored.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The DevicePath was connected.
 | 
						|
  @retval EFI_NOT_FOUND          The DevicePath was not found.
 | 
						|
  @retval EFI_NOT_FOUND          No driver was connected to DevicePath.
 | 
						|
  @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device
 | 
						|
                                 drivers on the DevicePath.
 | 
						|
  @retval EFI_UNSUPPORTED        The current TPL is not TPL_APPLICATION.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BootManagerPolicyConnectDevicePath (
 | 
						|
  IN EFI_BOOT_MANAGER_POLICY_PROTOCOL *This,
 | 
						|
  IN EFI_DEVICE_PATH                  *DevicePath,
 | 
						|
  IN BOOLEAN                          Recursive
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_HANDLE                          Controller;
 | 
						|
 | 
						|
  if (EfiGetCurrentTpl () != TPL_APPLICATION) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DevicePath == NULL) {
 | 
						|
    EfiBootManagerConnectAll ();
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Recursive) {
 | 
						|
    Status = EfiBootManagerConnectDevicePath (DevicePath, NULL);
 | 
						|
  } else {
 | 
						|
    Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &Controller);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      Status = gBS->ConnectController (Controller, NULL, DevicePath, FALSE);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
/**
 | 
						|
  Connect a class of devices using the platform Boot Manager policy.
 | 
						|
 | 
						|
  The ConnectDeviceClass() function allows the caller to request that the Boot
 | 
						|
  Manager connect a class of devices.
 | 
						|
 | 
						|
  If Class is EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID then the Boot Manager will
 | 
						|
  use platform policy to connect consoles. Some platforms may restrict the
 | 
						|
  number of consoles connected as they attempt to fast boot, and calling
 | 
						|
  ConnectDeviceClass() with a Class value of EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID
 | 
						|
  must connect the set of consoles that follow the Boot Manager platform policy,
 | 
						|
  and the EFI_SIMPLE_TEXT_INPUT_PROTOCOL, EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL, and
 | 
						|
  the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL are produced on the connected handles.
 | 
						|
  The Boot Manager may restrict which consoles get connect due to platform policy,
 | 
						|
  for example a security policy may require that a given console is not connected.
 | 
						|
 | 
						|
  If Class is EFI_BOOT_MANAGER_POLICY_NETWORK_GUID then the Boot Manager will
 | 
						|
  connect the protocols the platforms supports for UEFI general purpose network
 | 
						|
  applications on one or more handles. If more than one network controller is
 | 
						|
  available a platform will connect, one, many, or all of the networks based
 | 
						|
  on platform policy. Connecting UEFI networking protocols, like EFI_DHCP4_PROTOCOL,
 | 
						|
  does not establish connections on the network. The UEFI general purpose network
 | 
						|
  application that called ConnectDeviceClass() may need to use the published
 | 
						|
  protocols to establish the network connection. The Boot Manager can optionally
 | 
						|
  have a policy to establish a network connection.
 | 
						|
 | 
						|
  If Class is EFI_BOOT_MANAGER_POLICY_CONNECT_ALL_GUID then the Boot Manager
 | 
						|
  will connect all UEFI drivers using the UEFI Boot Service
 | 
						|
  EFI_BOOT_SERVICES.ConnectController(). If the Boot Manager has policy
 | 
						|
  associated with connect all UEFI drivers this policy will be used.
 | 
						|
 | 
						|
  A platform can also define platform specific Class values as a properly generated
 | 
						|
  EFI_GUID would never conflict with this specification.
 | 
						|
 | 
						|
  @param[in] This  A pointer to the EFI_BOOT_MANAGER_POLICY_PROTOCOL instance.
 | 
						|
  @param[in] Class A pointer to an EFI_GUID that represents a class of devices
 | 
						|
                   that will be connected using the Boot Mangers platform policy.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS      At least one devices of the Class was connected.
 | 
						|
  @retval EFI_DEVICE_ERROR Devices were not connected due to an error.
 | 
						|
  @retval EFI_NOT_FOUND    The Class is not supported by the platform.
 | 
						|
  @retval EFI_UNSUPPORTED  The current TPL is not TPL_APPLICATION.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BootManagerPolicyConnectDeviceClass (
 | 
						|
  IN EFI_BOOT_MANAGER_POLICY_PROTOCOL *This,
 | 
						|
  IN EFI_GUID                         *Class
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (EfiGetCurrentTpl () != TPL_APPLICATION) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompareGuid (Class, &gEfiBootManagerPolicyConnectAllGuid)) {
 | 
						|
    ConnectAllAndCreateNetworkDeviceList ();
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompareGuid (Class, &gEfiBootManagerPolicyConsoleGuid)) {
 | 
						|
    return EfiBootManagerConnectAllDefaultConsoles ();
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompareGuid (Class, &gEfiBootManagerPolicyNetworkGuid)) {
 | 
						|
    return ConnectNetwork ();
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
EFI_BOOT_MANAGER_POLICY_PROTOCOL  mBootManagerPolicy = {
 | 
						|
  EFI_BOOT_MANAGER_POLICY_PROTOCOL_REVISION,
 | 
						|
  BootManagerPolicyConnectDevicePath,
 | 
						|
  BootManagerPolicyConnectDeviceClass
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Install Boot Manager Policy Protocol.
 | 
						|
 | 
						|
  @param ImageHandle    The image handle.
 | 
						|
  @param SystemTable    The system table.
 | 
						|
 | 
						|
  @retval  EFI_SUCEESS  The Boot Manager Policy protocol is successfully installed.
 | 
						|
  @retval  Other        Return status from gBS->InstallMultipleProtocolInterfaces().
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BootManagerPolicyInitialize (
 | 
						|
  IN EFI_HANDLE                            ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE                      *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HANDLE                               Handle;
 | 
						|
 | 
						|
  ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiBootManagerPolicyProtocolGuid);
 | 
						|
 | 
						|
  Handle = NULL;
 | 
						|
  return gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                &Handle,
 | 
						|
                &gEfiBootManagerPolicyProtocolGuid, &mBootManagerPolicy,
 | 
						|
                NULL
 | 
						|
                );
 | 
						|
}
 |