--- /dev/null
+/** @file\r
+ This module produces Boot Manager Policy protocol.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Uefi.h>\r
+#include <Protocol/BootManagerPolicy.h>\r
+#include <Protocol/ManagedNetwork.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootManagerLib.h>\r
+\r
+CHAR16 mNetworkDeviceList[] = L"_NDL";\r
+\r
+/**\r
+ Connect all the system drivers to controllers and create the network device list in NV storage.\r
+\r
+ @retval EFI_SUCCESS Network devices are connected.\r
+ @retval EFI_DEVICE_ERROR No network device is connected.\r
+\r
+**/\r
+EFI_STATUS\r
+ConnectAllAndCreateNetworkDeviceList (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *Handles;\r
+ UINTN HandleCount;\r
+ EFI_DEVICE_PATH_PROTOCOL *SingleDevice;\r
+ EFI_DEVICE_PATH_PROTOCOL *Devices;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+\r
+ EfiBootManagerConnectAll ();\r
+\r
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiManagedNetworkServiceBindingProtocolGuid, NULL, &HandleCount, &Handles);\r
+ if (EFI_ERROR (Status)) {\r
+ Handles = NULL;\r
+ HandleCount = 0;\r
+ }\r
+\r
+ Devices = NULL;\r
+ while (HandleCount-- != 0) {\r
+ Status = gBS->HandleProtocol (Handles[HandleCount], &gEfiDevicePathProtocolGuid, (VOID **) &SingleDevice);\r
+ if (EFI_ERROR (Status) || (SingleDevice == NULL)) {\r
+ continue;\r
+ }\r
+ TempDevicePath = Devices;\r
+ Devices = AppendDevicePathInstance (Devices, SingleDevice);\r
+ if (TempDevicePath != NULL) {\r
+ FreePool (TempDevicePath);\r
+ }\r
+ }\r
+\r
+ if (Devices != NULL) {\r
+ Status = gRT->SetVariable (\r
+ mNetworkDeviceList,\r
+ &gEfiCallerIdGuid,\r
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+ GetDevicePathSize (Devices),\r
+ Devices\r
+ );\r
+ //\r
+ // Fails to save the network device list to NV storage is not a fatal error.\r
+ // Only impact is performance.\r
+ //\r
+ FreePool (Devices);\r
+ }\r
+\r
+ return (Devices == NULL) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Connect the network devices.\r
+\r
+ @retval EFI_SUCCESS At least one network device was connected.\r
+ @retval EFI_DEVICE_ERROR Network devices were not connected due to an error.\r
+**/\r
+EFI_STATUS\r
+ConnectNetwork (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN OneConnected;\r
+ EFI_DEVICE_PATH_PROTOCOL *Devices;\r
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *SingleDevice;\r
+ UINTN Size;\r
+\r
+ OneConnected = FALSE;\r
+ GetVariable2 (mNetworkDeviceList, &gEfiCallerIdGuid, (VOID **) &Devices, NULL);\r
+ TempDevicePath = Devices;\r
+ while (TempDevicePath != NULL) {\r
+ SingleDevice = GetNextDevicePathInstance (&TempDevicePath, &Size);\r
+ Status = EfiBootManagerConnectDevicePath (SingleDevice, NULL);\r
+ if (!EFI_ERROR (Status)) {\r
+ OneConnected = TRUE;\r
+ }\r
+ FreePool (SingleDevice);\r
+ }\r
+ if (Devices != NULL) {\r
+ FreePool (Devices);\r
+ }\r
+\r
+ if (OneConnected) {\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ //\r
+ // Cached network devices list doesn't exist or is NOT valid.\r
+ //\r
+ return ConnectAllAndCreateNetworkDeviceList ();\r
+ }\r
+}\r
+\r
+/**\r
+ Connect a device path following the platforms EFI Boot Manager policy.\r
+\r
+ The ConnectDevicePath() function allows the caller to connect a DevicePath using the\r
+ same policy as the EFI Boot Manger.\r
+\r
+ @param[in] This A pointer to the EFI_BOOT_MANAGER_POLICY_PROTOCOL instance.\r
+ @param[in] DevicePath Points to the start of the EFI device path to connect.\r
+ If DevicePath is NULL then all the controllers in the\r
+ system will be connected using the platforms EFI Boot\r
+ Manager policy.\r
+ @param[in] Recursive If TRUE, then ConnectController() is called recursively\r
+ until the entire tree of controllers below the \r
+ controller specified by DevicePath have been created.\r
+ If FALSE, then the tree of controllers is only expanded\r
+ one level. If DevicePath is NULL then Recursive is ignored.\r
+\r
+ @retval EFI_SUCCESS The DevicePath was connected.\r
+ @retval EFI_NOT_FOUND The DevicePath was not found.\r
+ @retval EFI_NOT_FOUND No driver was connected to DevicePath.\r
+ @retval EFI_SECURITY_VIOLATION The user has no permission to start UEFI device \r
+ drivers on the DevicePath.\r
+ @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerPolicyConnectDevicePath (\r
+ IN EFI_BOOT_MANAGER_POLICY_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH *DevicePath,\r
+ IN BOOLEAN Recursive\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE Controller;\r
+\r
+ if (EfiGetCurrentTpl () != TPL_APPLICATION) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (DevicePath == NULL) {\r
+ EfiBootManagerConnectAll ();\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (Recursive) {\r
+ Status = EfiBootManagerConnectDevicePath (DevicePath, NULL);\r
+ } else {\r
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &Controller);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->ConnectController (Controller, NULL, DevicePath, FALSE);\r
+ }\r
+ }\r
+ return Status;\r
+}\r
+/**\r
+ Connect a class of devices using the platform Boot Manager policy.\r
+\r
+ The ConnectDeviceClass() function allows the caller to request that the Boot\r
+ Manager connect a class of devices.\r
+\r
+ If Class is EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID then the Boot Manager will\r
+ use platform policy to connect consoles. Some platforms may restrict the \r
+ number of consoles connected as they attempt to fast boot, and calling\r
+ ConnectDeviceClass() with a Class value of EFI_BOOT_MANAGER_POLICY_CONSOLE_GUID\r
+ must connect the set of consoles that follow the Boot Manager platform policy,\r
+ and the EFI_SIMPLE_TEXT_INPUT_PROTOCOL, EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL, and\r
+ the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL are produced on the connected handles.\r
+ The Boot Manager may restrict which consoles get connect due to platform policy,\r
+ for example a security policy may require that a given console is not connected.\r
+\r
+ If Class is EFI_BOOT_MANAGER_POLICY_NETWORK_GUID then the Boot Manager will\r
+ connect the protocols the platforms supports for UEFI general purpose network\r
+ applications on one or more handles. If more than one network controller is\r
+ available a platform will connect, one, many, or all of the networks based\r
+ on platform policy. Connecting UEFI networking protocols, like EFI_DHCP4_PROTOCOL,\r
+ does not establish connections on the network. The UEFI general purpose network\r
+ application that called ConnectDeviceClass() may need to use the published\r
+ protocols to establish the network connection. The Boot Manager can optionally\r
+ have a policy to establish a network connection.\r
+ \r
+ If Class is EFI_BOOT_MANAGER_POLICY_CONNECT_ALL_GUID then the Boot Manager\r
+ will connect all UEFI drivers using the UEFI Boot Service\r
+ EFI_BOOT_SERVICES.ConnectController(). If the Boot Manager has policy\r
+ associated with connect all UEFI drivers this policy will be used.\r
+\r
+ A platform can also define platform specific Class values as a properly generated\r
+ EFI_GUID would never conflict with this specification.\r
+\r
+ @param[in] This A pointer to the EFI_BOOT_MANAGER_POLICY_PROTOCOL instance.\r
+ @param[in] Class A pointer to an EFI_GUID that represents a class of devices\r
+ that will be connected using the Boot Mangers platform policy.\r
+\r
+ @retval EFI_SUCCESS At least one devices of the Class was connected.\r
+ @retval EFI_DEVICE_ERROR Devices were not connected due to an error.\r
+ @retval EFI_NOT_FOUND The Class is not supported by the platform.\r
+ @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION.\r
+**/ \r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerPolicyConnectDeviceClass (\r
+ IN EFI_BOOT_MANAGER_POLICY_PROTOCOL *This,\r
+ IN EFI_GUID *Class\r
+ )\r
+{\r
+ if (EfiGetCurrentTpl () != TPL_APPLICATION) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (CompareGuid (Class, &gEfiBootManagerPolicyConnectAllGuid)) {\r
+ ConnectAllAndCreateNetworkDeviceList ();\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (CompareGuid (Class, &gEfiBootManagerPolicyConsoleGuid)) {\r
+ return EfiBootManagerConnectAllDefaultConsoles ();\r
+ }\r
+\r
+ if (CompareGuid (Class, &gEfiBootManagerPolicyNetworkGuid)) {\r
+ return ConnectNetwork ();\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_BOOT_MANAGER_POLICY_PROTOCOL mBootManagerPolicy = {\r
+ EFI_BOOT_MANAGER_POLICY_PROTOCOL_REVISION,\r
+ BootManagerPolicyConnectDevicePath,\r
+ BootManagerPolicyConnectDeviceClass\r
+};\r
+\r
+/**\r
+ Install Boot Manager Policy Protocol.\r
+\r
+ @param ImageHandle The image handle.\r
+ @param SystemTable The system table.\r
+\r
+ @retval EFI_SUCEESS The Boot Manager Policy protocol is successfully installed.\r
+ @retval Other Return status from gBS->InstallMultipleProtocolInterfaces().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BootManagerPolicyInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_HANDLE Handle;\r
+\r
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiBootManagerPolicyProtocolGuid);\r
+\r
+ Handle = NULL;\r
+ return gBS->InstallMultipleProtocolInterfaces (\r
+ &Handle,\r
+ &gEfiBootManagerPolicyProtocolGuid, &mBootManagerPolicy,\r
+ NULL\r
+ );\r
+}
\ No newline at end of file