diff --git a/RedfishPkg/Redfish.fdf.inc b/RedfishPkg/Redfish.fdf.inc index d3e849a0cb..60f31cfcee 100644 --- a/RedfishPkg/Redfish.fdf.inc +++ b/RedfishPkg/Redfish.fdf.inc @@ -16,4 +16,5 @@ INF RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf INF RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf INF RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf + INF RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf !endif diff --git a/RedfishPkg/RedfishComponents.dsc.inc b/RedfishPkg/RedfishComponents.dsc.inc index 735f2cd1c0..ccc62edf6a 100644 --- a/RedfishPkg/RedfishComponents.dsc.inc +++ b/RedfishPkg/RedfishComponents.dsc.inc @@ -18,4 +18,5 @@ RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf + RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf !endif diff --git a/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c new file mode 100644 index 0000000000..ff465d9ff3 --- /dev/null +++ b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c @@ -0,0 +1,265 @@ +/** @file + The common code of EDKII Redfish Configuration Handler driver. + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishConfigHandlerCommon.h" + +REDFISH_CONFIG_DRIVER_DATA gRedfishConfigData; // Only one Redfish service supproted + // on platform for the BIOS + // Redfish configuration. +EFI_EVENT gEndOfDxeEvent = NULL; +EFI_EVENT gExitBootServiceEvent = NULL; +EDKII_REDFISH_CREDENTIAL_PROTOCOL *gCredential = NULL; + +/** + Callback function executed when the EndOfDxe event group is signaled. + + @param[in] Event Event whose notification function is being invoked. + @param[out] Context Pointer to the Context buffer. + +**/ +VOID +EFIAPI +RedfishConfigOnEndOfDxe ( + IN EFI_EVENT Event, + OUT VOID *Context + ) +{ + EFI_STATUS Status; + + Status = gCredential->StopService (gCredential, ServiceStopTypeSecureBootDisabled); + if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) { + DEBUG ((DEBUG_ERROR, "Redfish credential protocol faied to stop service on EndOfDxe: %r", Status)); + } + + // + // Close event, so it will not be invoked again. + // + gBS->CloseEvent (gEndOfDxeEvent); + gEndOfDxeEvent = NULL; +} + +/** + Callback function executed when the ExitBootService event group is signaled. + + @param[in] Event Event whose notification function is being invoked. + @param[out] Context Pointer to the Context buffer + +**/ +VOID +EFIAPI +RedfishConfigOnExitBootService ( + IN EFI_EVENT Event, + OUT VOID *Context + ) +{ + EFI_STATUS Status; + + Status = gCredential->StopService (gCredential, ServiceStopTypeExitBootService); + if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) { + DEBUG ((DEBUG_ERROR, "Redfish credential protocol faied to stop service on ExitBootService: %r", Status)); + } +} + +/** + Unloads an image. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + +**/ +EFI_STATUS +RedfishConfigDriverCommonUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + if (gEndOfDxeEvent != NULL) { + gBS->CloseEvent (gEndOfDxeEvent); + gEndOfDxeEvent = NULL; + } + + if (gExitBootServiceEvent != NULL) { + gBS->CloseEvent (gExitBootServiceEvent); + gExitBootServiceEvent = NULL; + } + + if (gRedfishConfigData.Event != NULL) { + gBS->CloseEvent (gRedfishConfigData.Event); + gRedfishConfigData.Event = NULL; + } + + return EFI_SUCCESS; +} + +/** + This is the common code for Redfish configuration UEFI and DXE driver + initialization. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +RedfishConfigCommonInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + // + // Locate Redfish Credential Protocol to get credential for + // accessing to Redfish service. + // + Status = gBS->LocateProtocol (&gEdkIIRedfishCredentialProtocolGuid, NULL, (VOID **) &gCredential); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a: No Redfish Credential Protocol is installed on system.", __FUNCTION__)); + return Status; + } + // + // Create EndOfDxe Event. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + RedfishConfigOnEndOfDxe, + NULL, + &gEfiEndOfDxeEventGroupGuid, + &gEndOfDxeEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Fail to register End Of DXE event.", __FUNCTION__)); + return Status; + } + // + // Create Exit Boot Service event. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + RedfishConfigOnExitBootService, + NULL, + &gEfiEventExitBootServicesGuid, + &gExitBootServiceEvent + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (gEndOfDxeEvent); + gEndOfDxeEvent = NULL; + DEBUG ((DEBUG_ERROR, "%a: Fail to register Exit Boot Service event.", __FUNCTION__)); + return Status; + } + return EFI_SUCCESS; +} +/** + This is the common code to stop EDK2 Redfish feature driver. + + @retval EFI_SUCCESS All EDK2 Redfish feature drivers are + stopped. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +RedfishConfigCommonStop ( + VOID +) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINTN Index; + EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEdkIIRedfishConfigHandlerProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) { + return Status; + } + + Status = EFI_SUCCESS; + for (Index = 0; Index < NumberOfHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEdkIIRedfishConfigHandlerProtocolGuid, + (VOID**) &ConfigHandler + ); + ASSERT_EFI_ERROR (Status); + + Status = ConfigHandler->Stop (ConfigHandler); + if (EFI_ERROR (Status) && Status != EFI_UNSUPPORTED) { + DEBUG ((DEBUG_ERROR, "ERROR: Failed to stop Redfish config handler %p.\n", ConfigHandler)); + break; + } + } + return Status; +} +/** + Callback function executed when a Redfish Config Handler Protocol is installed + by EDK2 Redfish Feature Drivers. + +**/ +VOID +RedfishConfigHandlerInitialization ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler; + UINTN Index; + UINT32 Id; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEdkIIRedfishConfigHandlerProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return; + } + + for (Index = 0; Index < NumberOfHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer [Index], + &gEfiCallerIdGuid, + (VOID **) &Id + ); + if (!EFI_ERROR (Status)) { + continue; + } + + Status = gBS->HandleProtocol ( + HandleBuffer [Index], + &gEdkIIRedfishConfigHandlerProtocolGuid, + (VOID**) &ConfigHandler + ); + ASSERT_EFI_ERROR (Status); + Status = ConfigHandler->Init (ConfigHandler, &gRedfishConfigData.RedfishServiceInfo); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + DEBUG ((DEBUG_ERROR, "ERROR: Failed to init Redfish config handler %p.\n", ConfigHandler)); + } + // + // Install caller ID to indicate Redfish Configure Handler is initialized. + // + Status = gBS->InstallProtocolInterface ( + &HandleBuffer [Index], + &gEfiCallerIdGuid, + EFI_NATIVE_INTERFACE, + (VOID *)&gRedfishConfigData.CallerId + ); + ASSERT_EFI_ERROR (Status); + } +} diff --git a/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h new file mode 100644 index 0000000000..5e46c42219 --- /dev/null +++ b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h @@ -0,0 +1,101 @@ +/** @file + Common Header file for Redfish Configuration Handler UEFI driver + and DXE driver. + + (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EFI_REDFISH_CONFIG_HANDLER_COMMON_H_ +#define EFI_REDFISH_CONFIG_HANDLER_COMMON_H_ + +#include + +// +// Libraries +// +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Consumed Protocols +// +#include +#include + +// +// Driver Version +// +#define REDFISH_CONFIG_VERSION 0x00000001 + +/// +/// Internal structure used by Redfish Config DXE driver. +/// +typedef struct { + UINT32 CallerId; ///< Caller ID used to indicate Redfish Config Handler + ///< has been initiated + EFI_HANDLE Image; ///< Image handle of Redfish Config Driver + EFI_EVENT Event; ///< Event for the notification of EFI_REDFISH_CONFIG_HANDLER_PROTOCOL + REDFISH_CONFIG_SERVICE_INFORMATION RedfishServiceInfo; /// Redfish Service information discovered +} REDFISH_CONFIG_DRIVER_DATA; + +/** + Common code of unloading image for both UEFI/DXE Redfish Configuration drivers. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + +**/ +EFI_STATUS +RedfishConfigDriverCommonUnload ( + IN EFI_HANDLE ImageHandle + ); + +/** + This is the common code for Redfish configuration UEFI and DXE driver + initialization. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +RedfishConfigCommonInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + This is the common code to stop EDK2 Redfish feature driver. + + @retval EFI_SUCCESS All EDK2 Redfish feature drivers are + stopped. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +RedfishConfigCommonStop ( + VOID +); + +/** + Callback function executed when a Redfish Config Handler Protocol is installed + by EDK2 Redfish Feature Drivers. + +**/ +VOID +RedfishConfigHandlerInitialization ( + VOID + ); + +#endif diff --git a/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c new file mode 100644 index 0000000000..51378dff4f --- /dev/null +++ b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c @@ -0,0 +1,587 @@ +/** @file + The UEFI driver model driver which is responsible for locating the + Redfish service through Redfish host interface and executing EDKII + Redfish feature drivers. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "RedfishConfigHandlerDriver.h" + +EFI_EVENT gEfiRedfishDiscoverProtocolEvent = NULL; + +// +// Variables for using RFI Redfish Discover Protocol +// +VOID *gEfiRedfishDiscoverRegistration; +EFI_HANDLE gEfiRedfishDiscoverControllerHandle = NULL; +EFI_REDFISH_DISCOVER_PROTOCOL *gEfiRedfishDiscoverProtocol = NULL; +BOOLEAN gRedfishDiscoverActivated = FALSE; +BOOLEAN gRedfishServiceDiscovered = FALSE; +// +// Network interfaces discovered by EFI Redfish Discover Protocol. +// +UINTN gNumberOfNetworkInterfaces; +EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *gNetworkInterfaceInstances = NULL; +EFI_REDFISH_DISCOVERED_TOKEN *gRedfishDiscoveredToken = NULL; + +/// +/// Driver Binding Protocol instance +/// +EFI_DRIVER_BINDING_PROTOCOL gRedfishConfigDriverBinding = { + RedfishConfigDriverBindingSupported, + RedfishConfigDriverBindingStart, + RedfishConfigDriverBindingStop, + REDFISH_CONFIG_VERSION, + NULL, + NULL +}; + +/** + Stop acquiring Redfish service. + +**/ +VOID +RedfishConfigStopRedfishDiscovery ( + VOID +) +{ + if (gRedfishDiscoverActivated) { + // + // No more EFI Discover Protocol. + // + if (gEfiRedfishDiscoverProtocolEvent != NULL) { + gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent); + } + // + // Stop Redfish service discovery. + // + gEfiRedfishDiscoverProtocol->AbortAcquireRedfishService ( + gEfiRedfishDiscoverProtocol, + gNetworkInterfaceInstances + ); + gEfiRedfishDiscoverControllerHandle = NULL; + gEfiRedfishDiscoverProtocol = NULL; + gRedfishDiscoverActivated = FALSE; + gRedfishServiceDiscovered = FALSE; + } +} + +/** + Callback function executed when a Redfish Config Handler Protocol is installed. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context Pointer to the REDFISH_CONFIG_DRIVER_DATA buffer. + +**/ +VOID +EFIAPI +RedfishConfigHandlerInstalledCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + if (!gRedfishDiscoverActivated) { + // + // No Redfish service is discovered yet. + // + return; + } + + RedfishConfigHandlerInitialization (); +} + +/** + Tests to see if this driver supports a given controller. If a child device is provided, + it further tests to see if this driver supports creating a handle for the specified child device. + + This function checks to see if the driver specified by This supports the device specified by + ControllerHandle. Drivers will typically use the device path attached to + ControllerHandle and/or the services from the bus I/O abstraction attached to + ControllerHandle to determine if the driver supports ControllerHandle. This function + may be called many times during platform initialization. In order to reduce boot times, the tests + performed by this function must be very small, and take as little time as possible to execute. This + function must not change the state of any hardware devices, and this function must be aware that the + device specified by ControllerHandle may already be managed by the same driver or a + different driver. This function must match its calls to AllocatePages() with FreePages(), + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). + Because ControllerHandle may have been previously started by the same driver, if a protocol is + already in the opened state, then it must not be closed with CloseProtocol(). This is required + to guarantee the state of ControllerHandle is not modified by this function. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For bus drivers, if this parameter is not NULL, then + the bus driver must determine if the bus controller specified + by ControllerHandle and the child controller specified + by RemainingDevicePath are both supported by this + bus driver. + + @retval EFI_SUCCESS The device specified by ControllerHandle and + RemainingDevicePath is supported by the driver specified by This. + @retval EFI_UNSUPPORTED The device specified by ControllerHandle and + RemainingDevicePath is not supported by the driver specified by This. +**/ +EFI_STATUS +EFIAPI +RedfishConfigDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + EFI_REST_EX_PROTOCOL *RestEx; + EFI_STATUS Status; + EFI_HANDLE ChildHandle; + + ChildHandle = NULL; + + // + // Check if REST EX is ready. This just makes sure + // the network stack is brought up. + // + Status = NetLibCreateServiceChild ( + ControllerHandle, + This->ImageHandle, + &gEfiRestExServiceBindingProtocolGuid, + &ChildHandle + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Test if REST EX protocol is ready. + // + Status = gBS->OpenProtocol( + ChildHandle, + &gEfiRestExProtocolGuid, + (VOID**) &RestEx, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + } + NetLibDestroyServiceChild ( + ControllerHandle, + This->ImageHandle, + &gEfiRestExServiceBindingProtocolGuid, + ChildHandle + ); + return Status; +} + +/** + Starts a device controller or a bus controller. + + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, + but the following calling restrictions must be followed, or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For a bus driver, if this parameter is NULL, then handles + for all the children of Controller are created by this driver. + If this parameter is not NULL and the first Device Path Node is + not the End of Device Path Node, then only the handle for the + child device specified by the first Device Path Node of + RemainingDevicePath is created by this driver. + If the first Device Path Node of RemainingDevicePath is + the End of Device Path Node, no child handle is created by this + driver. + + @retval EFI_SUCCESS The driver is started. + @retval EFI_ALREADY_STARTED The driver was already started. + +**/ +EFI_STATUS +EFIAPI +RedfishConfigDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +{ + VOID *ConfigHandlerRegistration; + + if (gRedfishConfigData.Event != NULL) { + return EFI_ALREADY_STARTED; + } + + gRedfishConfigData.Event = EfiCreateProtocolNotifyEvent ( + &gEdkIIRedfishConfigHandlerProtocolGuid, + TPL_CALLBACK, + RedfishConfigHandlerInstalledCallback, + (VOID *)&gRedfishConfigData, + &ConfigHandlerRegistration + ); + return EFI_SUCCESS; +} + +/** + Stops a device controller or a bus controller. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed, or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + +**/ +EFI_STATUS +EFIAPI +RedfishConfigDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + EFI_STATUS Status; + + if (ControllerHandle == gEfiRedfishDiscoverControllerHandle) { + RedfishConfigStopRedfishDiscovery (); + } + gBS->CloseProtocol ( + ControllerHandle, + &gEfiRedfishDiscoverProtocolGuid, + gRedfishConfigData.Image, + gRedfishConfigData.Image + ); + + Status = RedfishConfigCommonStop (); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (gRedfishConfigData.Event != NULL) { + gBS->CloseEvent (gRedfishConfigData.Event); + gRedfishConfigData.Event = NULL; + } + return EFI_SUCCESS; +} + +/** + Callback function when Redfish service is discovered. + + @param[in] Event Event whose notification function is being invoked. + @param[out] Context Pointer to the Context buffer + +**/ +VOID +EFIAPI +RedfishServiceDiscoveredCallback ( + IN EFI_EVENT Event, + OUT VOID *Context + ) +{ + EFI_REDFISH_DISCOVERED_TOKEN *RedfishDiscoveredToken; + EFI_REDFISH_DISCOVERED_INSTANCE *RedfishInstance; + + if (gRedfishServiceDiscovered) { + // + // Only support one Redfish service on platform. + // + return; + } + + RedfishDiscoveredToken = (EFI_REDFISH_DISCOVERED_TOKEN *)Context; + RedfishInstance = RedfishDiscoveredToken->DiscoverList.RedfishInstances; + // + // Only pick up the first found Redfish service. + // + if (RedfishInstance->Status == EFI_SUCCESS) { + gRedfishConfigData.RedfishServiceInfo.RedfishServiceRestExHandle = RedfishInstance->Information.RedfishRestExHandle; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceVersion = RedfishInstance->Information.RedfishVersion; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceLocation = RedfishInstance->Information.Location; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceUuid = RedfishInstance->Information.Uuid; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceOs = RedfishInstance->Information.Os; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceOsVersion = RedfishInstance->Information.OsVersion; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceProduct = RedfishInstance->Information.Product; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceProductVer = RedfishInstance->Information.ProductVer; + gRedfishConfigData.RedfishServiceInfo.RedfishServiceUseHttps = RedfishInstance->Information.UseHttps; + gRedfishServiceDiscovered = TRUE; + } + + // + // Invoke RedfishConfigHandlerInstalledCallback to execute + // the initialization of Redfish Configure Handler instance. + // + RedfishConfigHandlerInstalledCallback (gRedfishConfigData.Event, &gRedfishConfigData); +} + +/** + Callback function executed when the EFI_REDFISH_DISCOVER_PROTOCOL + protocol interface is installed. + + @param[in] Event Event whose notification function is being invoked. + @param[out] Context Pointer to the Context buffer + +**/ +VOID +EFIAPI +RedfishDiscoverProtocolInstalled ( + IN EFI_EVENT Event, + OUT VOID *Context + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE HandleBuffer; + UINTN NetworkInterfaceIndex; + EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface; + EFI_REDFISH_DISCOVERED_TOKEN *ThisRedfishDiscoveredToken; + + DEBUG((DEBUG_INFO, "%a: New network interface is installed on system by EFI Redfish discover driver.\n", __FUNCTION__)); + + BufferSize = sizeof (EFI_HANDLE); + Status = gBS->LocateHandle ( + ByRegisterNotify, + NULL, + gEfiRedfishDiscoverRegistration, + &BufferSize, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: Can't locate handle with EFI_REDFISH_DISCOVER_PROTOCOL installed.\n", __FUNCTION__)); + } + gRedfishDiscoverActivated = TRUE; + if (gEfiRedfishDiscoverProtocol == NULL) { + gEfiRedfishDiscoverControllerHandle = HandleBuffer; + // + // First time to open EFI_REDFISH_DISCOVER_PROTOCOL. + // + Status = gBS->OpenProtocol( + gEfiRedfishDiscoverControllerHandle, + &gEfiRedfishDiscoverProtocolGuid, + (VOID **)&gEfiRedfishDiscoverProtocol, + gRedfishConfigData.Image, + gRedfishConfigData.Image, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gEfiRedfishDiscoverProtocol = NULL; + gRedfishDiscoverActivated = FALSE; + DEBUG((DEBUG_ERROR, "%a: Can't locate EFI_REDFISH_DISCOVER_PROTOCOL.\n", __FUNCTION__)); + return; + } + } + // + // Check the new found network interface. + // + if (gNetworkInterfaceInstances != NULL) { + FreePool (gNetworkInterfaceInstances); + } + Status = gEfiRedfishDiscoverProtocol->GetNetworkInterfaceList( + gEfiRedfishDiscoverProtocol, + gRedfishConfigData.Image, + &gNumberOfNetworkInterfaces, + &gNetworkInterfaceInstances + ); + if (EFI_ERROR (Status) || gNumberOfNetworkInterfaces == 0) { + DEBUG((DEBUG_ERROR, "%a: No network interfaces found on the handle.\n", __FUNCTION__)); + return; + } + + gRedfishDiscoveredToken = AllocateZeroPool (gNumberOfNetworkInterfaces * sizeof (EFI_REDFISH_DISCOVERED_TOKEN)); + if (gRedfishDiscoveredToken == NULL) { + DEBUG((DEBUG_ERROR, "%a: Not enough memory for EFI_REDFISH_DISCOVERED_TOKEN.\n", __FUNCTION__)); + return; + } + + ThisNetworkInterface = gNetworkInterfaceInstances; + ThisRedfishDiscoveredToken = gRedfishDiscoveredToken; + // + // Loop to discover Redfish service on each network interface. + // + for (NetworkInterfaceIndex = 0; NetworkInterfaceIndex < gNumberOfNetworkInterfaces; NetworkInterfaceIndex ++) { + // + // Initial this Redfish Discovered Token + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + RedfishServiceDiscoveredCallback, + (VOID *)ThisRedfishDiscoveredToken, + &ThisRedfishDiscoveredToken->Event + ); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: Failed to create event for Redfish discovered token.\n", __FUNCTION__)); + goto ErrorReturn; + } + ThisRedfishDiscoveredToken->Signature = REDFISH_DISCOVER_TOKEN_SIGNATURE; + ThisRedfishDiscoveredToken->DiscoverList.NumberOfServiceFound = 0; + ThisRedfishDiscoveredToken->DiscoverList.RedfishInstances = NULL; + // + // Acquire for Redfish service which is reported by + // Redfish Host Interface. + // + Status = gEfiRedfishDiscoverProtocol->AcquireRedfishService( + gEfiRedfishDiscoverProtocol, + gRedfishConfigData.Image, + ThisNetworkInterface, + EFI_REDFISH_DISCOVER_HOST_INTERFACE, + ThisRedfishDiscoveredToken + ); + ThisNetworkInterface ++; + ThisRedfishDiscoveredToken ++; + } + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "%a: Acquire Redfish service fail.\n", __FUNCTION__)); + goto ErrorReturn; + } + return; + +ErrorReturn: + if (gRedfishDiscoveredToken != NULL) { + FreePool(gRedfishDiscoveredToken); + } +} + +/** + Unloads an image. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + +**/ +EFI_STATUS +EFIAPI +RedfishConfigHandlerDriverUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_REDFISH_DISCOVERED_TOKEN *ThisRedfishDiscoveredToken; + UINTN NumberOfNetworkInterfacesIndex; + + RedfishConfigDriverCommonUnload (ImageHandle); + + RedfishConfigStopRedfishDiscovery (); + if (gRedfishDiscoveredToken != NULL) { + ThisRedfishDiscoveredToken = gRedfishDiscoveredToken; + for (NumberOfNetworkInterfacesIndex = 0; NumberOfNetworkInterfacesIndex < gNumberOfNetworkInterfaces; NumberOfNetworkInterfacesIndex ++) { + if (ThisRedfishDiscoveredToken->Event != NULL) { + gBS->CloseEvent (ThisRedfishDiscoveredToken->Event); + } + FreePool (ThisRedfishDiscoveredToken); + ThisRedfishDiscoveredToken ++; + } + gRedfishDiscoveredToken = NULL; + } + return EFI_SUCCESS; +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including + both device drivers and bus drivers. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +RedfishConfigHandlerDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + ZeroMem ((VOID *)&gRedfishConfigData, sizeof (REDFISH_CONFIG_DRIVER_DATA)); + gRedfishConfigData.Image = ImageHandle; + // + // Register event for EFI_REDFISH_DISCOVER_PROTOCOL protocol install + // notification. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + RedfishDiscoverProtocolInstalled, + NULL, + &gEfiRedfishDiscoverProtocolGuid, + &gEfiRedfishDiscoverProtocolEvent + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Fail to create event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __FUNCTION__)); + return Status; + } + Status = gBS->RegisterProtocolNotify ( + &gEfiRedfishDiscoverProtocolGuid, + gEfiRedfishDiscoverProtocolEvent, + &gEfiRedfishDiscoverRegistration + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __FUNCTION__)); + return Status; + } + + Status = RedfishConfigCommonInit (ImageHandle, SystemTable); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent); + gEfiRedfishDiscoverProtocolEvent = NULL; + return Status; + } + + // + // Install UEFI Driver Model protocol(s). + // + Status = EfiLibInstallDriverBinding ( + ImageHandle, + SystemTable, + &gRedfishConfigDriverBinding, + ImageHandle + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (gEndOfDxeEvent); + gEndOfDxeEvent = NULL; + gBS->CloseEvent (gExitBootServiceEvent); + gExitBootServiceEvent = NULL; + gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent); + gEfiRedfishDiscoverProtocolEvent = NULL; + DEBUG ((DEBUG_ERROR, "%a: Fail to install EFI Binding Protocol of EFI Redfish Config driver.", __FUNCTION__)); + return Status; + } + return Status; +} + diff --git a/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h new file mode 100644 index 0000000000..58202c41e2 --- /dev/null +++ b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h @@ -0,0 +1,159 @@ +/** @file + Header file of Redfish Configuration Handler UEFI driver. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EFI_REDFISH_CONFIG_HANDLER_DRIVER_H_ +#define EFI_REDFISH_CONFIG_HANDLER_DRIVER_H_ + +#include "RedfishConfigHandlerCommon.h" + +// +// UEFI Driver Model Protocols +// + +#include +#include +#include + +// +// Protocol instances +// +extern EFI_DRIVER_BINDING_PROTOCOL gRedfishConfigDriverBinding; + +extern REDFISH_CONFIG_DRIVER_DATA gRedfishConfigData; +extern EDKII_REDFISH_CREDENTIAL_PROTOCOL *gCredential; +extern EFI_EVENT gEndOfDxeEvent; +extern EFI_EVENT gExitBootServiceEvent; + +/** + Tests to see if this driver supports a given controller. If a child device is provided, + it further tests to see if this driver supports creating a handle for the specified child device. + + This function checks to see if the driver specified by This supports the device specified by + ControllerHandle. Drivers will typically use the device path attached to + ControllerHandle and/or the services from the bus I/O abstraction attached to + ControllerHandle to determine if the driver supports ControllerHandle. This function + may be called many times during platform initialization. In order to reduce boot times, the tests + performed by this function must be very small, and take as little time as possible to execute. This + function must not change the state of any hardware devices, and this function must be aware that the + device specified by ControllerHandle may already be managed by the same driver or a + different driver. This function must match its calls to AllocatePages() with FreePages(), + AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). + Because ControllerHandle may have been previously started by the same driver, if a protocol is + already in the opened state, then it must not be closed with CloseProtocol(). This is required + to guarantee the state of ControllerHandle is not modified by this function. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to test. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For bus drivers, if this parameter is not NULL, then + the bus driver must determine if the bus controller specified + by ControllerHandle and the child controller specified + by RemainingDevicePath are both supported by this + bus driver. + + @retval EFI_SUCCESS The device specified by ControllerHandle and + RemainingDevicePath is supported by the driver specified by This. + @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and + RemainingDevicePath is already being managed by the driver + specified by This. + @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and + RemainingDevicePath is already being managed by a different + driver or an application that requires exclusive access. + Currently not implemented. + @retval EFI_UNSUPPORTED The device specified by ControllerHandle and + RemainingDevicePath is not supported by the driver specified by This. +**/ +EFI_STATUS +EFIAPI +RedfishConfigDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Starts a device controller or a bus controller. + + The Start() function is designed to be invoked from the EFI boot service ConnectController(). + As a result, much of the error checking on the parameters to Start() has been moved into this + common boot service. It is legal to call Start() from other locations, + but the following calling restrictions must be followed, or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE. + 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned + EFI_DEVICE_PATH_PROTOCOL. + 3. Prior to calling Start(), the Supported() function for the driver specified by This must + have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle The handle of the controller to start. This handle + must support a protocol interface that supplies + an I/O abstraction to the driver. + @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This + parameter is ignored by device drivers, and is optional for bus + drivers. For a bus driver, if this parameter is NULL, then handles + for all the children of Controller are created by this driver. + If this parameter is not NULL and the first Device Path Node is + not the End of Device Path Node, then only the handle for the + child device specified by the first Device Path Node of + RemainingDevicePath is created by this driver. + If the first Device Path Node of RemainingDevicePath is + the End of Device Path Node, no child handle is created by this + driver. + + @retval EFI_SUCCESS The driver is started. + @retval EFI_ALREADY_STARTED The driver was already started. + +**/ +EFI_STATUS +EFIAPI +RedfishConfigDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +/** + Stops a device controller or a bus controller. + + The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). + As a result, much of the error checking on the parameters to Stop() has been moved + into this common boot service. It is legal to call Stop() from other locations, + but the following calling restrictions must be followed, or the system behavior will not be deterministic. + 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this + same driver's Start() function. + 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid + EFI_HANDLE. In addition, all of these handles must have been created in this driver's + Start() function, and the Start() function must have called OpenProtocol() on + ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + + @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + @param[in] ControllerHandle A handle to the device being stopped. The handle must + support a bus specific I/O protocol for the driver + to use to stop the device. + @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. + @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL + if NumberOfChildren is 0. + + @retval EFI_SUCCESS The device was stopped. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + +**/ +EFI_STATUS +EFIAPI +RedfishConfigDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ); +#endif diff --git a/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf new file mode 100644 index 0000000000..def91c7531 --- /dev/null +++ b/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf @@ -0,0 +1,60 @@ +## @file +# INF file for the UEFI driver model Redfish Configuration Handler +# Driver. +# +# Copyright (c) 2019, Intel Corporation. All rights reserved.
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x0001000b + BASE_NAME = RedfishConfigHandlerDriver + FILE_GUID = 6e881000-5749-11e8-9bf0-8cdcd426c973 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = RedfishConfigHandlerDriverEntryPoint + UNLOAD_IMAGE = RedfishConfigHandlerDriverUnload + +# +# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64 +# + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + NetworkPkg/NetworkPkg.dec + RedfishPkg/RedfishPkg.dec + +[Sources] + RedfishConfigHandlerDriver.h + RedfishConfigHandlerDriver.c + RedfishConfigHandlerCommon.h + RedfishConfigHandlerCommon.c + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + UefiLib + MemoryAllocationLib + NetLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiRedfishDiscoverProtocolGuid ## CONSUMES + gEfiRestExServiceBindingProtocolGuid + gEfiRestExProtocolGuid ## CONSUMES + gEdkIIRedfishCredentialProtocolGuid ## CONSUMES + gEdkIIRedfishConfigHandlerProtocolGuid ## CONSUMES + +[Guids] + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event + +[Depex] + TRUE +