+/**\r
+ Returns an array of protocol instance that matches the given protocol.\r
+\r
+ @param[in] Protocol Provides the protocol to search for.\r
+ @param[out] NoProtocols The number of protocols returned in Buffer.\r
+ @param[out] Buffer A pointer to the buffer to return the requested\r
+ array of protocol instances that match Protocol.\r
+ The returned buffer is allocated using\r
+ EFI_BOOT_SERVICES.AllocatePool(). The caller is\r
+ responsible for freeing this buffer with\r
+ EFI_BOOT_SERVICES.FreePool().\r
+\r
+ @retval EFI_SUCCESS The array of protocols was returned in Buffer,\r
+ and the number of protocols in Buffer was\r
+ returned in NoProtocols.\r
+ @retval EFI_NOT_FOUND No protocols found.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
+ matching results.\r
+ @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
+ @retval EFI_INVALID_PARAMETER NoProtocols is NULL.\r
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiLocateProtocolBuffer (\r
+ IN EFI_GUID *Protocol,\r
+ OUT UINTN *NoProtocols,\r
+ OUT VOID ***Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN NoHandles;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Check input parameters\r
+ //\r
+ if (Protocol == NULL || NoProtocols == NULL || Buffer == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Initialze output parameters\r
+ //\r
+ *NoProtocols = 0;\r
+ *Buffer = NULL;\r
+\r
+ //\r
+ // Retrieve the array of handles that support Protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ Protocol,\r
+ NULL,\r
+ &NoHandles,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Allocate array of protocol instances\r
+ //\r
+ Status = gBS->AllocatePool (\r
+ EfiBootServicesData,\r
+ NoHandles * sizeof (VOID *),\r
+ (VOID **)Buffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ ZeroMem (*Buffer, NoHandles * sizeof (VOID *));\r
+\r
+ //\r
+ // Lookup Protocol on each handle in HandleBuffer to fill in the array of\r
+ // protocol instances. Handle case where protocol instance was present when\r
+ // LocateHandleBuffer() was called, but is not present when HandleProtocol()\r
+ // is called.\r
+ //\r
+ for (Index = 0, *NoProtocols = 0; Index < NoHandles; Index++) {\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[Index],\r
+ Protocol,\r
+ &((*Buffer)[*NoProtocols])\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ (*NoProtocols)++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Free the handle buffer\r
+ //\r
+ gBS->FreePool (HandleBuffer);\r
+\r
+ //\r
+ // Make sure at least one protocol instance was found\r
+ //\r
+ if (*NoProtocols == 0) {\r
+ gBS->FreePool (*Buffer);\r
+ *Buffer = NULL;\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r