]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Locate.c
Update the copyright notice format
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Locate.c
CommitLineData
23c98c94 1/** @file\r
2 Locate handle functions\r
28a00297 3\r
cd5ebaa0
HT
4Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
409 Locates the handle to a device on the device path that best matches the specified protocol.\r
410\r
022c6d45 411 @param Protocol The protocol to search for.\r
412 @param DevicePath On input, a pointer to a pointer to the device\r
413 path. On output, the device path pointer is\r
414 modified to point to the remaining part of the\r
415 devicepath.\r
416 @param Device A pointer to the returned device handle.\r
162ed594 417\r
022c6d45 418 @retval EFI_SUCCESS The resulting handle was returned.\r
419 @retval EFI_NOT_FOUND No handles matched the search.\r
162ed594 420 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
421\r
422**/\r
28a00297 423EFI_STATUS\r
424EFIAPI\r
425CoreLocateDevicePath (\r
426 IN EFI_GUID *Protocol,\r
427 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
428 OUT EFI_HANDLE *Device\r
429 )\r
28a00297 430{\r
431 INTN SourceSize;\r
432 INTN Size;\r
433 INTN BestMatch;\r
434 UINTN HandleCount;\r
435 UINTN Index;\r
436 EFI_STATUS Status;\r
437 EFI_HANDLE *Handles;\r
438 EFI_HANDLE Handle;\r
439 EFI_DEVICE_PATH_PROTOCOL *SourcePath;\r
440 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
022c6d45 441\r
28a00297 442 if (Protocol == NULL) {\r
443 return EFI_INVALID_PARAMETER;\r
444 }\r
022c6d45 445\r
28a00297 446 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
447 return EFI_INVALID_PARAMETER;\r
448 }\r
022c6d45 449\r
28a00297 450 if (Device == NULL) {\r
451 return EFI_INVALID_PARAMETER;\r
452 }\r
022c6d45 453\r
4008328a 454 *Device = NULL;\r
28a00297 455 SourcePath = *DevicePath;\r
dc07b3d5 456 TmpDevicePath = SourcePath;\r
457 while (!IsDevicePathEnd (TmpDevicePath)) {\r
458 if (IsDevicePathEndInstance (TmpDevicePath)) {\r
459 //\r
460 // If DevicePath is a multi-instance device path,\r
461 // the function will operate on the first instance \r
462 //\r
463 break;\r
464 }\r
465 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
466 }\r
467\r
468 SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;\r
022c6d45 469\r
28a00297 470 //\r
471 // Get a list of all handles that support the requested protocol\r
472 //\r
473 Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
474 if (EFI_ERROR (Status) || HandleCount == 0) {\r
475 return EFI_NOT_FOUND;\r
476 }\r
477\r
478 BestMatch = -1;\r
479 for(Index = 0; Index < HandleCount; Index += 1) {\r
480 Handle = Handles[Index];\r
481 Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
482 if (EFI_ERROR (Status)) {\r
483 //\r
484 // If this handle doesn't support device path, then skip it\r
485 //\r
486 continue;\r
487 }\r
488\r
489 //\r
490 // Check if DevicePath is first part of SourcePath\r
491 //\r
9c4ac31c 492 Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
28a00297 493 if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {\r
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
506 *Device = Handle;\r
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
521 //\r
522 // Return the remaining part of the device path\r
523 //\r
524 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
525 return EFI_SUCCESS;\r
526}\r
527\r
528\r
44310938 529/**\r
28a00297 530 Return the first Protocol Interface that matches the Protocol GUID. If\r
8bc18cc6 531 Registration is passed in, return a Protocol Instance that was just add\r
532 to the system. If Registration is NULL return the first Protocol Interface\r
28a00297 533 you find.\r
534\r
022c6d45 535 @param Protocol The protocol to search for\r
536 @param Registration Optional Registration Key returned from\r
537 RegisterProtocolNotify()\r
538 @param Interface Return the Protocol interface (instance).\r
28a00297 539\r
022c6d45 540 @retval EFI_SUCCESS If a valid Interface is returned\r
541 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 542 @retval EFI_NOT_FOUND Protocol interface not found\r
28a00297 543\r
162ed594 544**/\r
545EFI_STATUS\r
546EFIAPI\r
547CoreLocateProtocol (\r
548 IN EFI_GUID *Protocol,\r
549 IN VOID *Registration OPTIONAL,\r
550 OUT VOID **Interface\r
551 )\r
28a00297 552{\r
553 EFI_STATUS Status;\r
554 LOCATE_POSITION Position;\r
555 PROTOCOL_NOTIFY *ProtNotify;\r
556 IHANDLE *Handle;\r
557\r
558 if (Interface == NULL) {\r
559 return EFI_INVALID_PARAMETER;\r
560 }\r
022c6d45 561\r
28a00297 562 if (Protocol == NULL) {\r
563 return EFI_NOT_FOUND;\r
564 }\r
022c6d45 565\r
28a00297 566 *Interface = NULL;\r
567 Status = EFI_SUCCESS;\r
568\r
569 //\r
570 // Set initial position\r
571 //\r
572 Position.Protocol = Protocol;\r
573 Position.SearchKey = Registration;\r
574 Position.Position = &gHandleList;\r
022c6d45 575\r
28a00297 576 //\r
577 // Lock the protocol database\r
578 //\r
579 CoreAcquireProtocolLock ();\r
580\r
581 mEfiLocateHandleRequest += 1;\r
582\r
e94a9ff7 583 if (Registration == NULL) {\r
28a00297 584 //\r
585 // Look up the protocol entry and set the head pointer\r
586 //\r
587 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
588 if (Position.ProtEntry == NULL) {\r
589 Status = EFI_NOT_FOUND;\r
590 goto Done;\r
591 }\r
592 Position.Position = &Position.ProtEntry->Protocols;\r
593\r
594 Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
595 } else {\r
022c6d45 596 Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);\r
28a00297 597 }\r
598\r
e94a9ff7 599 if (Handle == NULL) {\r
28a00297 600 Status = EFI_NOT_FOUND;\r
e94a9ff7 601 } else if (Registration != NULL) {\r
28a00297 602 //\r
603 // If this is a search by register notify and a handle was\r
604 // returned, update the register notification position\r
022c6d45 605 //\r
28a00297 606 ProtNotify = Registration;\r
607 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
608 }\r
609\r
610Done:\r
611 CoreReleaseProtocolLock ();\r
612 return Status;\r
613}\r
614\r
615\r
162ed594 616/**\r
617 Function returns an array of handles that support the requested protocol\r
618 in a buffer allocated from pool. This is a version of CoreLocateHandle()\r
619 that allocates a buffer for the caller.\r
620\r
022c6d45 621 @param SearchType Specifies which handle(s) are to be returned.\r
622 @param Protocol Provides the protocol to search by. This\r
623 parameter is only valid for SearchType\r
624 ByProtocol.\r
625 @param SearchKey Supplies the search key depending on the\r
626 SearchType.\r
627 @param NumberHandles The number of handles returned in Buffer.\r
628 @param Buffer A pointer to the buffer to return the requested\r
629 array of handles that support Protocol.\r
630\r
631 @retval EFI_SUCCESS The result array of handles was returned.\r
632 @retval EFI_NOT_FOUND No handles match the search.\r
633 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
634 matching results.\r
e94a9ff7 635 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.\r
162ed594 636\r
637**/\r
28a00297 638EFI_STATUS\r
639EFIAPI\r
640CoreLocateHandleBuffer (\r
641 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
642 IN EFI_GUID *Protocol OPTIONAL,\r
643 IN VOID *SearchKey OPTIONAL,\r
644 IN OUT UINTN *NumberHandles,\r
645 OUT EFI_HANDLE **Buffer\r
646 )\r
28a00297 647{\r
648 EFI_STATUS Status;\r
649 UINTN BufferSize;\r
650\r
651 if (NumberHandles == NULL) {\r
652 return EFI_INVALID_PARAMETER;\r
653 }\r
654\r
655 if (Buffer == NULL) {\r
656 return EFI_INVALID_PARAMETER;\r
657 }\r
658\r
659 BufferSize = 0;\r
660 *NumberHandles = 0;\r
661 *Buffer = NULL;\r
662 Status = CoreLocateHandle (\r
663 SearchType,\r
664 Protocol,\r
665 SearchKey,\r
666 &BufferSize,\r
667 *Buffer\r
668 );\r
669 //\r
670 // LocateHandleBuffer() returns incorrect status code if SearchType is\r
671 // invalid.\r
672 //\r
673 // Add code to correctly handle expected errors from CoreLocateHandle().\r
674 //\r
675 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
676 if (Status != EFI_INVALID_PARAMETER) {\r
677 Status = EFI_NOT_FOUND;\r
678 }\r
679 return Status;\r
680 }\r
681\r
9c4ac31c 682 *Buffer = AllocatePool (BufferSize);\r
28a00297 683 if (*Buffer == NULL) {\r
684 return EFI_OUT_OF_RESOURCES;\r
685 }\r
686\r
687 Status = CoreLocateHandle (\r
688 SearchType,\r
689 Protocol,\r
690 SearchKey,\r
691 &BufferSize,\r
692 *Buffer\r
693 );\r
694\r
e94a9ff7 695 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
28a00297 696 if (EFI_ERROR(Status)) {\r
697 *NumberHandles = 0;\r
698 }\r
699\r
700 return Status;\r
701}\r
702\r
703\r
162ed594 704\r