/** @file This is service binding for Hash driver. Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "Driver.h" EFI_SERVICE_BINDING_PROTOCOL mHash2ServiceBindingProtocol = { Hash2ServiceBindingCreateChild, Hash2ServiceBindingDestroyChild }; /** Creates a child handle with a set of I/O services. @param[in] This Protocol instance pointer. @param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL, then a new handle is created. If it is not NULL, then the I/O services are added to the existing child handle. @retval EFI_SUCCESS The protocol was added to ChildHandle. @retval EFI_INVALID_PARAMETER ChildHandle is NULL. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create the child. @retval Others The child handle was not created. **/ EFI_STATUS EFIAPI Hash2ServiceBindingCreateChild ( IN EFI_SERVICE_BINDING_PROTOCOL *This, IN OUT EFI_HANDLE *ChildHandle ) { EFI_STATUS Status; HASH2_SERVICE_DATA *Hash2ServiceData; HASH2_INSTANCE_DATA *Instance; EFI_TPL OldTpl; if ((This == NULL) || (ChildHandle == NULL)) { return EFI_INVALID_PARAMETER; } Hash2ServiceData = HASH2_SERVICE_DATA_FROM_THIS (This); // // Allocate buffer for the new instance. // Instance = AllocateZeroPool (sizeof (HASH2_INSTANCE_DATA)); if (Instance == NULL) { return EFI_OUT_OF_RESOURCES; } // // Init the instance data. // Instance->Signature = HASH2_INSTANCE_DATA_SIGNATURE; CopyMem (&Instance->Hash2Protocol, &mHash2Protocol, sizeof (Instance->Hash2Protocol)); Instance->Hash2ServiceData = Hash2ServiceData; Status = gBS->InstallMultipleProtocolInterfaces ( ChildHandle, &gEfiHash2ProtocolGuid, &Instance->Hash2Protocol, NULL ); if (EFI_ERROR (Status)) { FreePool (Instance); return Status; } Instance->Handle = *ChildHandle; // // Add the child instance into ChildrenList. // OldTpl = gBS->RaiseTPL (TPL_CALLBACK); InsertTailList (&Hash2ServiceData->ChildrenList, &Instance->InstEntry); gBS->RestoreTPL (OldTpl); return Status; } /** Destroys a child handle with a set of I/O services. The DestroyChild() function does the opposite of CreateChild(). It removes a protocol that was installed by CreateChild() from ChildHandle. If the removed protocol is the last protocol on ChildHandle, then ChildHandle is destroyed. @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. @param[in] ChildHandle Handle of the child to destroy. @retval EFI_SUCCESS The protocol was removed from ChildHandle. @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed. @retval EFI_INVALID_PARAMETER ChildHandle is NULL. @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle because its services are being used. @retval Others The child handle was not destroyed. **/ EFI_STATUS EFIAPI Hash2ServiceBindingDestroyChild ( IN EFI_SERVICE_BINDING_PROTOCOL *This, IN EFI_HANDLE ChildHandle ) { EFI_STATUS Status; HASH2_SERVICE_DATA *Hash2ServiceData; EFI_HASH2_PROTOCOL *Hash2Protocol; HASH2_INSTANCE_DATA *Instance; EFI_TPL OldTpl; LIST_ENTRY *Entry; if ((This == NULL) || (ChildHandle == NULL)) { return EFI_INVALID_PARAMETER; } Hash2ServiceData = HASH2_SERVICE_DATA_FROM_THIS (This); // // Check if this ChildHandle is valid // Instance = NULL; for(Entry = (&Hash2ServiceData->ChildrenList)->ForwardLink; Entry != (&Hash2ServiceData->ChildrenList); Entry = Entry->ForwardLink) { Instance = HASH2_INSTANCE_DATA_FROM_LINK (Entry); if (Instance->Handle == ChildHandle) { break; } else { Instance = NULL; } } if (Instance == NULL) { DEBUG ((EFI_D_ERROR, "Hash2ServiceBindingDestroyChild - Invalid handle\n")); return EFI_UNSUPPORTED; } // // Get HashProtocol // Status = gBS->HandleProtocol ( ChildHandle, &gEfiHash2ProtocolGuid, (VOID **)&Hash2Protocol ); if (EFI_ERROR (Status)) { return Status; } ASSERT (Hash2Protocol == &Instance->Hash2Protocol); // // Uninstall the Hash protocol. // Status = gBS->UninstallMultipleProtocolInterfaces ( ChildHandle, &gEfiHash2ProtocolGuid, &Instance->Hash2Protocol, NULL ); if (EFI_ERROR (Status)) { return Status; } OldTpl = gBS->RaiseTPL (TPL_CALLBACK); // // Remove this instance from the ChildrenList. // RemoveEntryList (&Instance->InstEntry); gBS->RestoreTPL (OldTpl); FreePool (Instance); return Status; } /** The entry point for Hash driver which installs the service binding protocol. @param[in] ImageHandle The image handle of the driver. @param[in] SystemTable The system table. @retval EFI_SUCCESS The service binding protocols is successfully installed. @retval Others Other errors as indicated. **/ EFI_STATUS EFIAPI Hash2DriverEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; HASH2_SERVICE_DATA *Hash2ServiceData; // // Initialize the Hash Service Data. // Hash2ServiceData = AllocateZeroPool (sizeof (HASH2_SERVICE_DATA)); if (Hash2ServiceData == NULL) { return EFI_OUT_OF_RESOURCES; } Hash2ServiceData->Signature = HASH2_SERVICE_DATA_SIGNATURE; CopyMem (&Hash2ServiceData->ServiceBinding, &mHash2ServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL)); InitializeListHead (&Hash2ServiceData->ChildrenList); // // Install the HASH Service Binding Protocol // Status = gBS->InstallMultipleProtocolInterfaces ( &Hash2ServiceData->ServiceHandle, &gEfiHash2ServiceBindingProtocolGuid, &Hash2ServiceData->ServiceBinding, NULL ); if (EFI_ERROR (Status)) { FreePool (Hash2ServiceData); } return Status; }