| /** @file | |
| This is service binding for Hash driver. | |
| Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials are licensed and made available under | |
| the terms and conditions of the BSD License that accompanies this distribution. | |
| The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php. | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #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_SUCCES The protocol was added to ChildHandle. | |
| @retval EFI_INVALID_PARAMETER ChildHandle is NULL. | |
| @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe 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_SUCCES 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_SUCCES 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; | |
| } |