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