]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Locate.c
Fix minor coding style issue for ScsiReadCapacity16Command() API in UefiScsiLib
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Locate.c
CommitLineData
23c98c94 1/** @file\r
2 Locate handle functions\r
28a00297 3\r
23c98c94 4Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
5All rights reserved. This program and the accompanying materials\r
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
203 //\r
204 // Enumerate out the matching handles\r
205 //\r
206 mEfiLocateHandleRequest += 1;\r
207 for (; ;) {\r
208 //\r
209 // Get the next handle. If no more handles, stop\r
210 //\r
211 Handle = GetNext (&Position, &Interface);\r
212 if (NULL == Handle) {\r
213 break;\r
214 }\r
215\r
216 //\r
217 // Increase the resulting buffer size, and if this handle\r
218 // fits return it\r
219 //\r
220 ResultSize += sizeof(Handle);\r
221 if (ResultSize <= *BufferSize) {\r
222 *ResultBuffer = Handle;\r
223 ResultBuffer += 1;\r
224 }\r
225 }\r
226\r
227 //\r
228 // If the result is a zero length buffer, then there were no\r
229 // matching handles\r
230 //\r
231 if (ResultSize == 0) {\r
232 Status = EFI_NOT_FOUND;\r
233 } else {\r
234 //\r
235 // Return the resulting buffer size. If it's larger than what\r
236 // was passed, then set the error code\r
237 //\r
238 if (ResultSize > *BufferSize) {\r
239 Status = EFI_BUFFER_TOO_SMALL;\r
022c6d45 240 }\r
241\r
28a00297 242 *BufferSize = ResultSize;\r
243\r
244 if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {\r
245 //\r
246 // If this is a search by register notify and a handle was\r
247 // returned, update the register notification position\r
022c6d45 248 //\r
28a00297 249 ProtNotify = SearchKey;\r
250 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
251 }\r
252 }\r
253\r
254 CoreReleaseProtocolLock ();\r
255 return Status;\r
256}\r
257\r
258\r
162ed594 259\r
260/**\r
261 Routine to get the next Handle, when you are searching for all handles.\r
262\r
022c6d45 263 @param Position Information about which Handle to seach for.\r
264 @param Interface Return the interface structure for the matching\r
265 protocol.\r
162ed594 266\r
e94a9ff7 267 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 268 Otherwise,NULL is returned.\r
162ed594 269\r
270**/\r
28a00297 271IHANDLE *\r
272CoreGetNextLocateAllHandles (\r
273 IN OUT LOCATE_POSITION *Position,\r
274 OUT VOID **Interface\r
275 )\r
28a00297 276{\r
277 IHANDLE *Handle;\r
278\r
279 //\r
280 // Next handle\r
281 //\r
282 Position->Position = Position->Position->ForwardLink;\r
283\r
284 //\r
285 // If not at the end of the list, get the handle\r
286 //\r
4008328a 287 Handle = NULL;\r
28a00297 288 *Interface = NULL;\r
289 if (Position->Position != &gHandleList) {\r
290 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
291 }\r
292\r
293 return Handle;\r
294}\r
295\r
296\r
162ed594 297\r
298/**\r
299 Routine to get the next Handle, when you are searching for register protocol\r
300 notifies.\r
301\r
022c6d45 302 @param Position Information about which Handle to seach for.\r
303 @param Interface Return the interface structure for the matching\r
304 protocol.\r
162ed594 305\r
e94a9ff7 306 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 307 Otherwise,NULL is returned.\r
162ed594 308\r
309**/\r
28a00297 310IHANDLE *\r
311CoreGetNextLocateByRegisterNotify (\r
312 IN OUT LOCATE_POSITION *Position,\r
313 OUT VOID **Interface\r
314 )\r
28a00297 315{\r
316 IHANDLE *Handle;\r
317 PROTOCOL_NOTIFY *ProtNotify;\r
318 PROTOCOL_INTERFACE *Prot;\r
022c6d45 319 LIST_ENTRY *Link;\r
28a00297 320\r
4008328a 321 Handle = NULL;\r
28a00297 322 *Interface = NULL;\r
323 ProtNotify = Position->SearchKey;\r
324\r
325 //\r
326 // If this is the first request, get the next handle\r
327 //\r
328 if (ProtNotify != NULL) {\r
329 ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
330 Position->SearchKey = NULL;\r
331\r
332 //\r
333 // If not at the end of the list, get the next handle\r
334 //\r
335 Link = ProtNotify->Position->ForwardLink;\r
336 if (Link != &ProtNotify->Protocol->Protocols) {\r
337 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 338 Handle = Prot->Handle;\r
28a00297 339 *Interface = Prot->Interface;\r
022c6d45 340 }\r
28a00297 341 }\r
342\r
343 return Handle;\r
344}\r
345\r
346\r
162ed594 347/**\r
348 Routine to get the next Handle, when you are searching for a given protocol.\r
349\r
022c6d45 350 @param Position Information about which Handle to seach for.\r
351 @param Interface Return the interface structure for the matching\r
352 protocol.\r
162ed594 353\r
e94a9ff7 354 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 355 Otherwise,NULL is returned.\r
162ed594 356\r
357**/\r
28a00297 358IHANDLE *\r
359CoreGetNextLocateByProtocol (\r
360 IN OUT LOCATE_POSITION *Position,\r
361 OUT VOID **Interface\r
362 )\r
28a00297 363{\r
364 IHANDLE *Handle;\r
365 LIST_ENTRY *Link;\r
366 PROTOCOL_INTERFACE *Prot;\r
022c6d45 367\r
4008328a 368 Handle = NULL;\r
28a00297 369 *Interface = NULL;\r
370 for (; ;) {\r
371 //\r
372 // Next entry\r
373 //\r
374 Link = Position->Position->ForwardLink;\r
375 Position->Position = Link;\r
376\r
377 //\r
378 // If not at the end, return the handle\r
379 //\r
380 if (Link == &Position->ProtEntry->Protocols) {\r
4008328a 381 Handle = NULL;\r
28a00297 382 break;\r
383 }\r
384\r
385 //\r
386 // Get the handle\r
387 //\r
388 Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 389 Handle = Prot->Handle;\r
28a00297 390 *Interface = Prot->Interface;\r
391\r
392 //\r
022c6d45 393 // If this handle has not been returned this request, then\r
28a00297 394 // return it now\r
395 //\r
396 if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
397 Handle->LocateRequest = mEfiLocateHandleRequest;\r
398 break;\r
399 }\r
400 }\r
401\r
402 return Handle;\r
403}\r
404\r
405\r
162ed594 406/**\r
407 Locates the handle to a device on the device path that best matches the specified protocol.\r
408\r
022c6d45 409 @param Protocol The protocol to search for.\r
410 @param DevicePath On input, a pointer to a pointer to the device\r
411 path. On output, the device path pointer is\r
412 modified to point to the remaining part of the\r
413 devicepath.\r
414 @param Device A pointer to the returned device handle.\r
162ed594 415\r
022c6d45 416 @retval EFI_SUCCESS The resulting handle was returned.\r
417 @retval EFI_NOT_FOUND No handles matched the search.\r
162ed594 418 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
419\r
420**/\r
28a00297 421EFI_STATUS\r
422EFIAPI\r
423CoreLocateDevicePath (\r
424 IN EFI_GUID *Protocol,\r
425 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
426 OUT EFI_HANDLE *Device\r
427 )\r
28a00297 428{\r
429 INTN SourceSize;\r
430 INTN Size;\r
431 INTN BestMatch;\r
432 UINTN HandleCount;\r
433 UINTN Index;\r
434 EFI_STATUS Status;\r
435 EFI_HANDLE *Handles;\r
436 EFI_HANDLE Handle;\r
437 EFI_DEVICE_PATH_PROTOCOL *SourcePath;\r
438 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
022c6d45 439\r
28a00297 440 if (Protocol == NULL) {\r
441 return EFI_INVALID_PARAMETER;\r
442 }\r
022c6d45 443\r
28a00297 444 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
445 return EFI_INVALID_PARAMETER;\r
446 }\r
022c6d45 447\r
28a00297 448 if (Device == NULL) {\r
449 return EFI_INVALID_PARAMETER;\r
450 }\r
022c6d45 451\r
4008328a 452 *Device = NULL;\r
28a00297 453 SourcePath = *DevicePath;\r
9c4ac31c 454 SourceSize = GetDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
022c6d45 455\r
28a00297 456 //\r
457 // The source path can only have 1 instance\r
458 //\r
9c4ac31c 459 if (IsDevicePathMultiInstance (SourcePath)) {\r
162ed594 460 DEBUG((DEBUG_ERROR, "LocateDevicePath: Device path has too many instances\n"));\r
28a00297 461 return EFI_INVALID_PARAMETER;\r
462 }\r
463\r
464 //\r
465 // Get a list of all handles that support the requested protocol\r
466 //\r
467 Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
468 if (EFI_ERROR (Status) || HandleCount == 0) {\r
469 return EFI_NOT_FOUND;\r
470 }\r
471\r
472 BestMatch = -1;\r
473 for(Index = 0; Index < HandleCount; Index += 1) {\r
474 Handle = Handles[Index];\r
475 Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
476 if (EFI_ERROR (Status)) {\r
477 //\r
478 // If this handle doesn't support device path, then skip it\r
479 //\r
480 continue;\r
481 }\r
482\r
483 //\r
484 // Check if DevicePath is first part of SourcePath\r
485 //\r
9c4ac31c 486 Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
28a00297 487 if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {\r
488 //\r
489 // If the size is equal to the best match, then we\r
490 // have a duplice device path for 2 different device\r
491 // handles\r
492 //\r
493 ASSERT (Size != BestMatch);\r
022c6d45 494\r
28a00297 495 //\r
496 // We've got a match, see if it's the best match so far\r
497 //\r
498 if (Size > BestMatch) {\r
499 BestMatch = Size;\r
500 *Device = Handle;\r
501 }\r
502 }\r
503 }\r
504\r
505 CoreFreePool (Handles);\r
022c6d45 506\r
28a00297 507 //\r
022c6d45 508 // If there wasn't any match, then no parts of the device path was found.\r
28a00297 509 // Which is strange since there is likely a "root level" device path in the system.\r
510 //\r
511 if (BestMatch == -1) {\r
512 return EFI_NOT_FOUND;\r
513 }\r
514\r
515 //\r
516 // Return the remaining part of the device path\r
517 //\r
518 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
519 return EFI_SUCCESS;\r
520}\r
521\r
522\r
44310938 523/**\r
28a00297 524 Return the first Protocol Interface that matches the Protocol GUID. If\r
525 Registration is pasased in return a Protocol Instance that was just add\r
526 to the system. If Retistration is NULL return the first Protocol Interface\r
527 you find.\r
528\r
022c6d45 529 @param Protocol The protocol to search for\r
530 @param Registration Optional Registration Key returned from\r
531 RegisterProtocolNotify()\r
532 @param Interface Return the Protocol interface (instance).\r
28a00297 533\r
022c6d45 534 @retval EFI_SUCCESS If a valid Interface is returned\r
535 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 536 @retval EFI_NOT_FOUND Protocol interface not found\r
28a00297 537\r
162ed594 538**/\r
539EFI_STATUS\r
540EFIAPI\r
541CoreLocateProtocol (\r
542 IN EFI_GUID *Protocol,\r
543 IN VOID *Registration OPTIONAL,\r
544 OUT VOID **Interface\r
545 )\r
28a00297 546{\r
547 EFI_STATUS Status;\r
548 LOCATE_POSITION Position;\r
549 PROTOCOL_NOTIFY *ProtNotify;\r
550 IHANDLE *Handle;\r
551\r
552 if (Interface == NULL) {\r
553 return EFI_INVALID_PARAMETER;\r
554 }\r
022c6d45 555\r
28a00297 556 if (Protocol == NULL) {\r
557 return EFI_NOT_FOUND;\r
558 }\r
022c6d45 559\r
28a00297 560 *Interface = NULL;\r
561 Status = EFI_SUCCESS;\r
562\r
563 //\r
564 // Set initial position\r
565 //\r
566 Position.Protocol = Protocol;\r
567 Position.SearchKey = Registration;\r
568 Position.Position = &gHandleList;\r
022c6d45 569\r
28a00297 570 //\r
571 // Lock the protocol database\r
572 //\r
573 CoreAcquireProtocolLock ();\r
574\r
575 mEfiLocateHandleRequest += 1;\r
576\r
e94a9ff7 577 if (Registration == NULL) {\r
28a00297 578 //\r
579 // Look up the protocol entry and set the head pointer\r
580 //\r
581 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
582 if (Position.ProtEntry == NULL) {\r
583 Status = EFI_NOT_FOUND;\r
584 goto Done;\r
585 }\r
586 Position.Position = &Position.ProtEntry->Protocols;\r
587\r
588 Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
589 } else {\r
022c6d45 590 Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);\r
28a00297 591 }\r
592\r
e94a9ff7 593 if (Handle == NULL) {\r
28a00297 594 Status = EFI_NOT_FOUND;\r
e94a9ff7 595 } else if (Registration != NULL) {\r
28a00297 596 //\r
597 // If this is a search by register notify and a handle was\r
598 // returned, update the register notification position\r
022c6d45 599 //\r
28a00297 600 ProtNotify = Registration;\r
601 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
602 }\r
603\r
604Done:\r
605 CoreReleaseProtocolLock ();\r
606 return Status;\r
607}\r
608\r
609\r
162ed594 610/**\r
611 Function returns an array of handles that support the requested protocol\r
612 in a buffer allocated from pool. This is a version of CoreLocateHandle()\r
613 that allocates a buffer for the caller.\r
614\r
022c6d45 615 @param SearchType Specifies which handle(s) are to be returned.\r
616 @param Protocol Provides the protocol to search by. This\r
617 parameter is only valid for SearchType\r
618 ByProtocol.\r
619 @param SearchKey Supplies the search key depending on the\r
620 SearchType.\r
621 @param NumberHandles The number of handles returned in Buffer.\r
622 @param Buffer A pointer to the buffer to return the requested\r
623 array of handles that support Protocol.\r
624\r
625 @retval EFI_SUCCESS The result array of handles was returned.\r
626 @retval EFI_NOT_FOUND No handles match the search.\r
627 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
628 matching results.\r
e94a9ff7 629 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.\r
162ed594 630\r
631**/\r
28a00297 632EFI_STATUS\r
633EFIAPI\r
634CoreLocateHandleBuffer (\r
635 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
636 IN EFI_GUID *Protocol OPTIONAL,\r
637 IN VOID *SearchKey OPTIONAL,\r
638 IN OUT UINTN *NumberHandles,\r
639 OUT EFI_HANDLE **Buffer\r
640 )\r
28a00297 641{\r
642 EFI_STATUS Status;\r
643 UINTN BufferSize;\r
644\r
645 if (NumberHandles == NULL) {\r
646 return EFI_INVALID_PARAMETER;\r
647 }\r
648\r
649 if (Buffer == NULL) {\r
650 return EFI_INVALID_PARAMETER;\r
651 }\r
652\r
653 BufferSize = 0;\r
654 *NumberHandles = 0;\r
655 *Buffer = NULL;\r
656 Status = CoreLocateHandle (\r
657 SearchType,\r
658 Protocol,\r
659 SearchKey,\r
660 &BufferSize,\r
661 *Buffer\r
662 );\r
663 //\r
664 // LocateHandleBuffer() returns incorrect status code if SearchType is\r
665 // invalid.\r
666 //\r
667 // Add code to correctly handle expected errors from CoreLocateHandle().\r
668 //\r
669 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
670 if (Status != EFI_INVALID_PARAMETER) {\r
671 Status = EFI_NOT_FOUND;\r
672 }\r
673 return Status;\r
674 }\r
675\r
9c4ac31c 676 *Buffer = AllocatePool (BufferSize);\r
28a00297 677 if (*Buffer == NULL) {\r
678 return EFI_OUT_OF_RESOURCES;\r
679 }\r
680\r
681 Status = CoreLocateHandle (\r
682 SearchType,\r
683 Protocol,\r
684 SearchKey,\r
685 &BufferSize,\r
686 *Buffer\r
687 );\r
688\r
e94a9ff7 689 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
28a00297 690 if (EFI_ERROR(Status)) {\r
691 *NumberHandles = 0;\r
692 }\r
693\r
694 return Status;\r
695}\r
696\r
697\r
162ed594 698\r