|
@@ -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.<BR>
|
|
|
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
|
|
|
+
|
|
|
+ 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;
|
|
|
+}
|
|
|
+
|