/** * * Copyright (C) 2018, Marvell International Ltd. and its affiliates. * * SPDX-License-Identifier: BSD-2-Clause-Patent * **/ #include #include #include #include #include #include #include /* * Check if the driver type matches the requested value. * In case of the success open the GPIO protocol and return. */ STATIC EFI_STATUS MvGpioFindMatchingDriver ( IN MV_GPIO_DRIVER_TYPE GpioDriverType, IN EFI_HANDLE HandleBuffer, IN EFI_DEVICE_PATH *DevicePath, IN OUT EMBEDDED_GPIO **GpioProtocol ) { MV_GPIO_DEVICE_PATH *GpioDevicePath; EFI_STATUS Status; while (!IsDevicePathEndType (DevicePath)) { /* Check if GpioDriverType matches one found in the device path */ GpioDevicePath = (MV_GPIO_DEVICE_PATH *)DevicePath; if (GpioDevicePath->GpioDriverType != GpioDriverType) { DevicePath = NextDevicePathNode (DevicePath); continue; } /* * Open GpioProtocol. With EFI_OPEN_PROTOCOL_GET_PROTOCOL attribute * the consumer is not obliged to call CloseProtocol. */ Status = gBS->OpenProtocol (HandleBuffer, &gEmbeddedGpioProtocolGuid, (VOID **)GpioProtocol, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); return Status; } return EFI_NOT_FOUND; } /* * Select desired protocol producer upon MV_GPIO_DRIVER_TYPE * field of driver's MV_GPIO_DEVICE_PATH. */ EFI_STATUS EFIAPI MvGpioGetProtocol ( IN MV_GPIO_DRIVER_TYPE GpioDriverType, IN OUT EMBEDDED_GPIO **GpioProtocol ) { EFI_DEVICE_PATH *DevicePath; EFI_HANDLE *HandleBuffer; EFI_STATUS Status; UINTN HandleCount; UINTN Index; /* Locate Handles of all EMBEDDED_GPIO producers */ Status = gBS->LocateHandleBuffer (ByProtocol, &gEmbeddedGpioProtocolGuid, NULL, &HandleCount, &HandleBuffer); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: Unable to locate handles\n", __FUNCTION__)); return Status; } /* Iterate over all protocol producers */ for (Index = 0; Index < HandleCount; Index++) { /* Open device path protocol installed on each handle */ Status = gBS->OpenProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: Unable to find DevicePath\n", __FUNCTION__)); continue; } /* * Check if the driver type matches the requested value. * In case of the success open the GPIO protocol and return. * If there is no match, repeat procedure with the next handle. */ Status = MvGpioFindMatchingDriver (GpioDriverType, HandleBuffer[Index], DevicePath, GpioProtocol); if (Status == EFI_NOT_FOUND) { continue; } else if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a: Unable to open GPIO protocol\n", __FUNCTION__)); } gBS->FreePool (HandleBuffer); return Status; } /* No matching GPIO protocol producer was found */ gBS->FreePool (HandleBuffer); return EFI_NOT_FOUND; }