]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Locate.c
MdeModulePkg: Return invalid param in LocateProtocol for Protocol==NULL
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Locate.c
CommitLineData
23c98c94 1/** @file\r
2 Locate handle functions\r
28a00297 3\r
415fc5e5 4Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
cd5ebaa0 5This program and the accompanying materials\r
23c98c94 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
504214c4 9\r
23c98c94 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
28a00297 12\r
504214c4 13**/\r
28a00297 14\r
9c4ac31c 15#include "DxeMain.h"\r
ec90508b 16#include "Handle.h"\r
28a00297 17\r
18//\r
19// ProtocolRequest - Last LocateHandle request ID\r
20//\r
21UINTN mEfiLocateHandleRequest = 0;\r
22\r
23//\r
24// Internal prototypes\r
25//\r
26\r
27typedef struct {\r
28 EFI_GUID *Protocol;\r
29 VOID *SearchKey;\r
30 LIST_ENTRY *Position;\r
31 PROTOCOL_ENTRY *ProtEntry;\r
32} LOCATE_POSITION;\r
33\r
022c6d45 34typedef\r
28a00297 35IHANDLE *\r
36(* CORE_GET_NEXT) (\r
37 IN OUT LOCATE_POSITION *Position,\r
38 OUT VOID **Interface\r
39 );\r
40\r
162ed594 41/**\r
42 Routine to get the next Handle, when you are searching for all handles.\r
43\r
022c6d45 44 @param Position Information about which Handle to seach for.\r
45 @param Interface Return the interface structure for the matching\r
46 protocol.\r
162ed594 47\r
022c6d45 48 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 49 Otherwise,NULL is returned.\r
162ed594 50\r
51**/\r
28a00297 52IHANDLE *\r
53CoreGetNextLocateAllHandles (\r
54 IN OUT LOCATE_POSITION *Position,\r
55 OUT VOID **Interface\r
56 );\r
57\r
162ed594 58/**\r
59 Routine to get the next Handle, when you are searching for register protocol\r
60 notifies.\r
61\r
022c6d45 62 @param Position Information about which Handle to seach for.\r
63 @param Interface Return the interface structure for the matching\r
64 protocol.\r
162ed594 65\r
022c6d45 66 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 67 Otherwise,NULL is returned.\r
162ed594 68\r
69**/\r
28a00297 70IHANDLE *\r
71CoreGetNextLocateByRegisterNotify (\r
72 IN OUT LOCATE_POSITION *Position,\r
73 OUT VOID **Interface\r
74 );\r
75\r
162ed594 76/**\r
77 Routine to get the next Handle, when you are searching for a given protocol.\r
78\r
022c6d45 79 @param Position Information about which Handle to seach for.\r
80 @param Interface Return the interface structure for the matching\r
81 protocol.\r
162ed594 82\r
022c6d45 83 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 84 Otherwise,NULL is returned.\r
162ed594 85\r
86**/\r
28a00297 87IHANDLE *\r
88CoreGetNextLocateByProtocol (\r
89 IN OUT LOCATE_POSITION *Position,\r
90 OUT VOID **Interface\r
91 );\r
92\r
28a00297 93\r
162ed594 94/**\r
95 Locates the requested handle(s) and returns them in Buffer.\r
96\r
022c6d45 97 @param SearchType The type of search to perform to locate the\r
98 handles\r
99 @param Protocol The protocol to search for\r
100 @param SearchKey Dependant on SearchType\r
101 @param BufferSize On input the size of Buffer. On output the\r
102 size of data returned.\r
103 @param Buffer The buffer to return the results in\r
104\r
105 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is\r
106 returned in BufferSize.\r
107 @retval EFI_INVALID_PARAMETER Invalid parameter\r
108 @retval EFI_SUCCESS Successfully found the requested handle(s) and\r
162ed594 109 returns them in Buffer.\r
28a00297 110\r
162ed594 111**/\r
28a00297 112EFI_STATUS\r
113EFIAPI\r
114CoreLocateHandle (\r
115 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
116 IN EFI_GUID *Protocol OPTIONAL,\r
117 IN VOID *SearchKey OPTIONAL,\r
118 IN OUT UINTN *BufferSize,\r
119 OUT EFI_HANDLE *Buffer\r
120 )\r
28a00297 121{\r
122 EFI_STATUS Status;\r
123 LOCATE_POSITION Position;\r
124 PROTOCOL_NOTIFY *ProtNotify;\r
125 CORE_GET_NEXT GetNext;\r
126 UINTN ResultSize;\r
127 IHANDLE *Handle;\r
128 IHANDLE **ResultBuffer;\r
129 VOID *Interface;\r
022c6d45 130\r
28a00297 131 if (BufferSize == NULL) {\r
29dd3b04 132 return EFI_INVALID_PARAMETER;\r
28a00297 133 }\r
022c6d45 134\r
28a00297 135 if ((*BufferSize > 0) && (Buffer == NULL)) {\r
136 return EFI_INVALID_PARAMETER;\r
137 }\r
022c6d45 138\r
28a00297 139 GetNext = NULL;\r
e94a9ff7 140\r
28a00297 141 //\r
142 // Set initial position\r
143 //\r
28a00297 144 Position.Protocol = Protocol;\r
145 Position.SearchKey = SearchKey;\r
146 Position.Position = &gHandleList;\r
147\r
148 ResultSize = 0;\r
149 ResultBuffer = (IHANDLE **) Buffer;\r
150 Status = EFI_SUCCESS;\r
151\r
152 //\r
153 // Lock the protocol database\r
154 //\r
28a00297 155 CoreAcquireProtocolLock ();\r
156\r
157 //\r
158 // Get the search function based on type\r
159 //\r
160 switch (SearchType) {\r
022c6d45 161 case AllHandles:\r
162 GetNext = CoreGetNextLocateAllHandles;\r
28a00297 163 break;\r
164\r
022c6d45 165 case ByRegisterNotify:\r
28a00297 166 //\r
167 // Must have SearchKey for locate ByRegisterNotify\r
168 //\r
169 if (SearchKey == NULL) {\r
170 Status = EFI_INVALID_PARAMETER;\r
171 break;\r
172 }\r
022c6d45 173 GetNext = CoreGetNextLocateByRegisterNotify;\r
28a00297 174 break;\r
175\r
022c6d45 176 case ByProtocol:\r
28a00297 177 GetNext = CoreGetNextLocateByProtocol;\r
178 if (Protocol == NULL) {\r
179 Status = EFI_INVALID_PARAMETER;\r
180 break;\r
181 }\r
182 //\r
183 // Look up the protocol entry and set the head pointer\r
184 //\r
185 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
186 if (Position.ProtEntry == NULL) {\r
187 Status = EFI_NOT_FOUND;\r
188 break;\r
189 }\r
190 Position.Position = &Position.ProtEntry->Protocols;\r
191 break;\r
192\r
193 default:\r
194 Status = EFI_INVALID_PARAMETER;\r
195 break;\r
196 }\r
197\r
198 if (EFI_ERROR(Status)) {\r
199 CoreReleaseProtocolLock ();\r
200 return Status;\r
201 }\r
202\r
d2fbaaab 203 ASSERT (GetNext != NULL);\r
28a00297 204 //\r
205 // Enumerate out the matching handles\r
206 //\r
207 mEfiLocateHandleRequest += 1;\r
208 for (; ;) {\r
209 //\r
210 // Get the next handle. If no more handles, stop\r
211 //\r
212 Handle = GetNext (&Position, &Interface);\r
213 if (NULL == Handle) {\r
214 break;\r
215 }\r
216\r
217 //\r
218 // Increase the resulting buffer size, and if this handle\r
219 // fits return it\r
220 //\r
221 ResultSize += sizeof(Handle);\r
222 if (ResultSize <= *BufferSize) {\r
223 *ResultBuffer = Handle;\r
224 ResultBuffer += 1;\r
225 }\r
226 }\r
227\r
228 //\r
229 // If the result is a zero length buffer, then there were no\r
230 // matching handles\r
231 //\r
232 if (ResultSize == 0) {\r
233 Status = EFI_NOT_FOUND;\r
234 } else {\r
235 //\r
236 // Return the resulting buffer size. If it's larger than what\r
237 // was passed, then set the error code\r
238 //\r
239 if (ResultSize > *BufferSize) {\r
240 Status = EFI_BUFFER_TOO_SMALL;\r
022c6d45 241 }\r
242\r
28a00297 243 *BufferSize = ResultSize;\r
244\r
245 if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {\r
246 //\r
247 // If this is a search by register notify and a handle was\r
248 // returned, update the register notification position\r
022c6d45 249 //\r
d2fbaaab 250 ASSERT (SearchKey != NULL);\r
28a00297 251 ProtNotify = SearchKey;\r
252 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
253 }\r
254 }\r
255\r
256 CoreReleaseProtocolLock ();\r
257 return Status;\r
258}\r
259\r
260\r
162ed594 261\r
262/**\r
263 Routine to get the next Handle, when you are searching for all handles.\r
264\r
022c6d45 265 @param Position Information about which Handle to seach for.\r
266 @param Interface Return the interface structure for the matching\r
267 protocol.\r
162ed594 268\r
e94a9ff7 269 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 270 Otherwise,NULL is returned.\r
162ed594 271\r
272**/\r
28a00297 273IHANDLE *\r
274CoreGetNextLocateAllHandles (\r
275 IN OUT LOCATE_POSITION *Position,\r
276 OUT VOID **Interface\r
277 )\r
28a00297 278{\r
279 IHANDLE *Handle;\r
280\r
281 //\r
282 // Next handle\r
283 //\r
284 Position->Position = Position->Position->ForwardLink;\r
285\r
286 //\r
287 // If not at the end of the list, get the handle\r
288 //\r
4008328a 289 Handle = NULL;\r
28a00297 290 *Interface = NULL;\r
291 if (Position->Position != &gHandleList) {\r
292 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
293 }\r
294\r
295 return Handle;\r
296}\r
297\r
298\r
162ed594 299\r
300/**\r
301 Routine to get the next Handle, when you are searching for register protocol\r
302 notifies.\r
303\r
022c6d45 304 @param Position Information about which Handle to seach for.\r
305 @param Interface Return the interface structure for the matching\r
306 protocol.\r
162ed594 307\r
e94a9ff7 308 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 309 Otherwise,NULL is returned.\r
162ed594 310\r
311**/\r
28a00297 312IHANDLE *\r
313CoreGetNextLocateByRegisterNotify (\r
314 IN OUT LOCATE_POSITION *Position,\r
315 OUT VOID **Interface\r
316 )\r
28a00297 317{\r
318 IHANDLE *Handle;\r
319 PROTOCOL_NOTIFY *ProtNotify;\r
320 PROTOCOL_INTERFACE *Prot;\r
022c6d45 321 LIST_ENTRY *Link;\r
28a00297 322\r
4008328a 323 Handle = NULL;\r
28a00297 324 *Interface = NULL;\r
325 ProtNotify = Position->SearchKey;\r
326\r
327 //\r
328 // If this is the first request, get the next handle\r
329 //\r
330 if (ProtNotify != NULL) {\r
331 ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
332 Position->SearchKey = NULL;\r
333\r
334 //\r
335 // If not at the end of the list, get the next handle\r
336 //\r
337 Link = ProtNotify->Position->ForwardLink;\r
338 if (Link != &ProtNotify->Protocol->Protocols) {\r
339 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 340 Handle = Prot->Handle;\r
28a00297 341 *Interface = Prot->Interface;\r
022c6d45 342 }\r
28a00297 343 }\r
344\r
345 return Handle;\r
346}\r
347\r
348\r
162ed594 349/**\r
350 Routine to get the next Handle, when you are searching for a given protocol.\r
351\r
022c6d45 352 @param Position Information about which Handle to seach for.\r
353 @param Interface Return the interface structure for the matching\r
354 protocol.\r
162ed594 355\r
e94a9ff7 356 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 357 Otherwise,NULL is returned.\r
162ed594 358\r
359**/\r
28a00297 360IHANDLE *\r
361CoreGetNextLocateByProtocol (\r
362 IN OUT LOCATE_POSITION *Position,\r
363 OUT VOID **Interface\r
364 )\r
28a00297 365{\r
366 IHANDLE *Handle;\r
367 LIST_ENTRY *Link;\r
368 PROTOCOL_INTERFACE *Prot;\r
022c6d45 369\r
4008328a 370 Handle = NULL;\r
28a00297 371 *Interface = NULL;\r
372 for (; ;) {\r
373 //\r
374 // Next entry\r
375 //\r
376 Link = Position->Position->ForwardLink;\r
377 Position->Position = Link;\r
378\r
379 //\r
380 // If not at the end, return the handle\r
381 //\r
382 if (Link == &Position->ProtEntry->Protocols) {\r
4008328a 383 Handle = NULL;\r
28a00297 384 break;\r
385 }\r
386\r
387 //\r
388 // Get the handle\r
389 //\r
390 Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 391 Handle = Prot->Handle;\r
28a00297 392 *Interface = Prot->Interface;\r
393\r
394 //\r
022c6d45 395 // If this handle has not been returned this request, then\r
28a00297 396 // return it now\r
397 //\r
398 if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
399 Handle->LocateRequest = mEfiLocateHandleRequest;\r
400 break;\r
401 }\r
402 }\r
403\r
404 return Handle;\r
405}\r
406\r
407\r
162ed594 408/**\r
a36a9b37 409 Locates the handle to a device on the device path that supports the specified protocol.\r
162ed594 410\r
a36a9b37 411 @param Protocol Specifies the protocol to search for.\r
412 @param DevicePath On input, a pointer to a pointer to the device path. On output, the device\r
413 path pointer is modified to point to the remaining part of the device\r
414 path.\r
415 @param Device A pointer to the returned device handle.\r
162ed594 416\r
a36a9b37 417 @retval EFI_SUCCESS The resulting handle was returned.\r
418 @retval EFI_NOT_FOUND No handles match the search.\r
419 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
420 @retval EFI_INVALID_PARAMETER DevicePath is NULL.\r
421 @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.\r
162ed594 422\r
423**/\r
28a00297 424EFI_STATUS\r
425EFIAPI\r
426CoreLocateDevicePath (\r
427 IN EFI_GUID *Protocol,\r
428 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
429 OUT EFI_HANDLE *Device\r
430 )\r
28a00297 431{\r
432 INTN SourceSize;\r
433 INTN Size;\r
434 INTN BestMatch;\r
435 UINTN HandleCount;\r
436 UINTN Index;\r
437 EFI_STATUS Status;\r
438 EFI_HANDLE *Handles;\r
439 EFI_HANDLE Handle;\r
a36a9b37 440 EFI_HANDLE BestDevice;\r
28a00297 441 EFI_DEVICE_PATH_PROTOCOL *SourcePath;\r
442 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
022c6d45 443\r
28a00297 444 if (Protocol == NULL) {\r
445 return EFI_INVALID_PARAMETER;\r
446 }\r
022c6d45 447\r
28a00297 448 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
449 return EFI_INVALID_PARAMETER;\r
450 }\r
022c6d45 451\r
4e1005ec 452 Handles = NULL;\r
a36a9b37 453 BestDevice = NULL;\r
28a00297 454 SourcePath = *DevicePath;\r
dc07b3d5 455 TmpDevicePath = SourcePath;\r
456 while (!IsDevicePathEnd (TmpDevicePath)) {\r
457 if (IsDevicePathEndInstance (TmpDevicePath)) {\r
458 //\r
459 // If DevicePath is a multi-instance device path,\r
460 // the function will operate on the first instance \r
461 //\r
462 break;\r
463 }\r
464 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
465 }\r
466\r
467 SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;\r
022c6d45 468\r
28a00297 469 //\r
470 // Get a list of all handles that support the requested protocol\r
471 //\r
472 Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
473 if (EFI_ERROR (Status) || HandleCount == 0) {\r
474 return EFI_NOT_FOUND;\r
475 }\r
476\r
477 BestMatch = -1;\r
478 for(Index = 0; Index < HandleCount; Index += 1) {\r
479 Handle = Handles[Index];\r
480 Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
481 if (EFI_ERROR (Status)) {\r
482 //\r
483 // If this handle doesn't support device path, then skip it\r
484 //\r
485 continue;\r
486 }\r
487\r
488 //\r
489 // Check if DevicePath is first part of SourcePath\r
490 //\r
9c4ac31c 491 Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
cd7bfc2c
ED
492 ASSERT (Size >= 0);\r
493 if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, (UINTN) Size) == 0) {\r
28a00297 494 //\r
495 // If the size is equal to the best match, then we\r
dc07b3d5 496 // have a duplicate device path for 2 different device\r
28a00297 497 // handles\r
498 //\r
499 ASSERT (Size != BestMatch);\r
022c6d45 500\r
28a00297 501 //\r
502 // We've got a match, see if it's the best match so far\r
503 //\r
504 if (Size > BestMatch) {\r
505 BestMatch = Size;\r
a36a9b37 506 BestDevice = Handle;\r
28a00297 507 }\r
508 }\r
509 }\r
510\r
511 CoreFreePool (Handles);\r
022c6d45 512\r
28a00297 513 //\r
022c6d45 514 // If there wasn't any match, then no parts of the device path was found.\r
28a00297 515 // Which is strange since there is likely a "root level" device path in the system.\r
516 //\r
517 if (BestMatch == -1) {\r
518 return EFI_NOT_FOUND;\r
519 }\r
520\r
a36a9b37 521 if (Device == NULL) {\r
522 return EFI_INVALID_PARAMETER;\r
523 }\r
524 *Device = BestDevice;\r
525 \r
28a00297 526 //\r
527 // Return the remaining part of the device path\r
528 //\r
529 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
530 return EFI_SUCCESS;\r
531}\r
532\r
533\r
44310938 534/**\r
28a00297 535 Return the first Protocol Interface that matches the Protocol GUID. If\r
8bc18cc6 536 Registration is passed in, return a Protocol Instance that was just add\r
537 to the system. If Registration is NULL return the first Protocol Interface\r
28a00297 538 you find.\r
539\r
022c6d45 540 @param Protocol The protocol to search for\r
541 @param Registration Optional Registration Key returned from\r
542 RegisterProtocolNotify()\r
543 @param Interface Return the Protocol interface (instance).\r
28a00297 544\r
022c6d45 545 @retval EFI_SUCCESS If a valid Interface is returned\r
546 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 547 @retval EFI_NOT_FOUND Protocol interface not found\r
28a00297 548\r
162ed594 549**/\r
550EFI_STATUS\r
551EFIAPI\r
552CoreLocateProtocol (\r
553 IN EFI_GUID *Protocol,\r
554 IN VOID *Registration OPTIONAL,\r
555 OUT VOID **Interface\r
556 )\r
28a00297 557{\r
558 EFI_STATUS Status;\r
559 LOCATE_POSITION Position;\r
560 PROTOCOL_NOTIFY *ProtNotify;\r
561 IHANDLE *Handle;\r
562\r
415fc5e5 563 if ((Interface == NULL) || (Protocol == NULL)) {\r
28a00297 564 return EFI_INVALID_PARAMETER;\r
565 }\r
022c6d45 566\r
28a00297 567 *Interface = NULL;\r
568 Status = EFI_SUCCESS;\r
569\r
570 //\r
571 // Set initial position\r
572 //\r
573 Position.Protocol = Protocol;\r
574 Position.SearchKey = Registration;\r
575 Position.Position = &gHandleList;\r
022c6d45 576\r
28a00297 577 //\r
578 // Lock the protocol database\r
579 //\r
ae6945b6
RN
580 Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock);\r
581 if (EFI_ERROR (Status)) {\r
582 return EFI_NOT_FOUND;\r
583 }\r
28a00297 584\r
585 mEfiLocateHandleRequest += 1;\r
586\r
e94a9ff7 587 if (Registration == NULL) {\r
28a00297 588 //\r
589 // Look up the protocol entry and set the head pointer\r
590 //\r
591 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
592 if (Position.ProtEntry == NULL) {\r
593 Status = EFI_NOT_FOUND;\r
594 goto Done;\r
595 }\r
596 Position.Position = &Position.ProtEntry->Protocols;\r
597\r
598 Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
599 } else {\r
022c6d45 600 Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);\r
28a00297 601 }\r
602\r
e94a9ff7 603 if (Handle == NULL) {\r
28a00297 604 Status = EFI_NOT_FOUND;\r
e94a9ff7 605 } else if (Registration != NULL) {\r
28a00297 606 //\r
607 // If this is a search by register notify and a handle was\r
608 // returned, update the register notification position\r
022c6d45 609 //\r
28a00297 610 ProtNotify = Registration;\r
611 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
612 }\r
613\r
614Done:\r
615 CoreReleaseProtocolLock ();\r
616 return Status;\r
617}\r
618\r
619\r
162ed594 620/**\r
621 Function returns an array of handles that support the requested protocol\r
622 in a buffer allocated from pool. This is a version of CoreLocateHandle()\r
623 that allocates a buffer for the caller.\r
624\r
022c6d45 625 @param SearchType Specifies which handle(s) are to be returned.\r
626 @param Protocol Provides the protocol to search by. This\r
627 parameter is only valid for SearchType\r
628 ByProtocol.\r
629 @param SearchKey Supplies the search key depending on the\r
630 SearchType.\r
631 @param NumberHandles The number of handles returned in Buffer.\r
632 @param Buffer A pointer to the buffer to return the requested\r
633 array of handles that support Protocol.\r
634\r
635 @retval EFI_SUCCESS The result array of handles was returned.\r
636 @retval EFI_NOT_FOUND No handles match the search.\r
637 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
638 matching results.\r
6393d9c8 639 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.\r
162ed594 640\r
641**/\r
28a00297 642EFI_STATUS\r
643EFIAPI\r
644CoreLocateHandleBuffer (\r
645 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
646 IN EFI_GUID *Protocol OPTIONAL,\r
647 IN VOID *SearchKey OPTIONAL,\r
648 IN OUT UINTN *NumberHandles,\r
649 OUT EFI_HANDLE **Buffer\r
650 )\r
28a00297 651{\r
652 EFI_STATUS Status;\r
653 UINTN BufferSize;\r
654\r
655 if (NumberHandles == NULL) {\r
656 return EFI_INVALID_PARAMETER;\r
657 }\r
658\r
659 if (Buffer == NULL) {\r
660 return EFI_INVALID_PARAMETER;\r
661 }\r
662\r
663 BufferSize = 0;\r
664 *NumberHandles = 0;\r
665 *Buffer = NULL;\r
666 Status = CoreLocateHandle (\r
667 SearchType,\r
668 Protocol,\r
669 SearchKey,\r
670 &BufferSize,\r
671 *Buffer\r
672 );\r
673 //\r
674 // LocateHandleBuffer() returns incorrect status code if SearchType is\r
675 // invalid.\r
676 //\r
677 // Add code to correctly handle expected errors from CoreLocateHandle().\r
678 //\r
679 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
680 if (Status != EFI_INVALID_PARAMETER) {\r
681 Status = EFI_NOT_FOUND;\r
682 }\r
683 return Status;\r
684 }\r
685\r
9c4ac31c 686 *Buffer = AllocatePool (BufferSize);\r
28a00297 687 if (*Buffer == NULL) {\r
688 return EFI_OUT_OF_RESOURCES;\r
689 }\r
690\r
691 Status = CoreLocateHandle (\r
692 SearchType,\r
693 Protocol,\r
694 SearchKey,\r
695 &BufferSize,\r
696 *Buffer\r
697 );\r
698\r
e94a9ff7 699 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
28a00297 700 if (EFI_ERROR(Status)) {\r
701 *NumberHandles = 0;\r
702 }\r
703\r
704 return Status;\r
705}\r
706\r
707\r
162ed594 708\r