]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Locate.c
Remove notice for PXE_OPFLAGS_GET_MEDIA_STATUS and PXE_STATFLAGS_GET_STATUS_NO_MEDIA_...
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Locate.c
CommitLineData
23c98c94 1/** @file\r
2 Locate handle functions\r
28a00297 3\r
dc07b3d5 4Copyright (c) 2006 - 2009, Intel Corporation. <BR>\r
23c98c94 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
dc07b3d5 454 TmpDevicePath = SourcePath;\r
455 while (!IsDevicePathEnd (TmpDevicePath)) {\r
456 if (IsDevicePathEndInstance (TmpDevicePath)) {\r
457 //\r
458 // If DevicePath is a multi-instance device path,\r
459 // the function will operate on the first instance \r
460 //\r
461 break;\r
462 }\r
463 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
464 }\r
465\r
466 SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;\r
022c6d45 467\r
28a00297 468 //\r
469 // Get a list of all handles that support the requested protocol\r
470 //\r
471 Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
472 if (EFI_ERROR (Status) || HandleCount == 0) {\r
473 return EFI_NOT_FOUND;\r
474 }\r
475\r
476 BestMatch = -1;\r
477 for(Index = 0; Index < HandleCount; Index += 1) {\r
478 Handle = Handles[Index];\r
479 Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
480 if (EFI_ERROR (Status)) {\r
481 //\r
482 // If this handle doesn't support device path, then skip it\r
483 //\r
484 continue;\r
485 }\r
486\r
487 //\r
488 // Check if DevicePath is first part of SourcePath\r
489 //\r
9c4ac31c 490 Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
28a00297 491 if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {\r
492 //\r
493 // If the size is equal to the best match, then we\r
dc07b3d5 494 // have a duplicate device path for 2 different device\r
28a00297 495 // handles\r
496 //\r
497 ASSERT (Size != BestMatch);\r
022c6d45 498\r
28a00297 499 //\r
500 // We've got a match, see if it's the best match so far\r
501 //\r
502 if (Size > BestMatch) {\r
503 BestMatch = Size;\r
504 *Device = Handle;\r
505 }\r
506 }\r
507 }\r
508\r
509 CoreFreePool (Handles);\r
022c6d45 510\r
28a00297 511 //\r
022c6d45 512 // If there wasn't any match, then no parts of the device path was found.\r
28a00297 513 // Which is strange since there is likely a "root level" device path in the system.\r
514 //\r
515 if (BestMatch == -1) {\r
516 return EFI_NOT_FOUND;\r
517 }\r
518\r
519 //\r
520 // Return the remaining part of the device path\r
521 //\r
522 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
523 return EFI_SUCCESS;\r
524}\r
525\r
526\r
44310938 527/**\r
28a00297 528 Return the first Protocol Interface that matches the Protocol GUID. If\r
8bc18cc6 529 Registration is passed in, return a Protocol Instance that was just add\r
530 to the system. If Registration is NULL return the first Protocol Interface\r
28a00297 531 you find.\r
532\r
022c6d45 533 @param Protocol The protocol to search for\r
534 @param Registration Optional Registration Key returned from\r
535 RegisterProtocolNotify()\r
536 @param Interface Return the Protocol interface (instance).\r
28a00297 537\r
022c6d45 538 @retval EFI_SUCCESS If a valid Interface is returned\r
539 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 540 @retval EFI_NOT_FOUND Protocol interface not found\r
28a00297 541\r
162ed594 542**/\r
543EFI_STATUS\r
544EFIAPI\r
545CoreLocateProtocol (\r
546 IN EFI_GUID *Protocol,\r
547 IN VOID *Registration OPTIONAL,\r
548 OUT VOID **Interface\r
549 )\r
28a00297 550{\r
551 EFI_STATUS Status;\r
552 LOCATE_POSITION Position;\r
553 PROTOCOL_NOTIFY *ProtNotify;\r
554 IHANDLE *Handle;\r
555\r
556 if (Interface == NULL) {\r
557 return EFI_INVALID_PARAMETER;\r
558 }\r
022c6d45 559\r
28a00297 560 if (Protocol == NULL) {\r
561 return EFI_NOT_FOUND;\r
562 }\r
022c6d45 563\r
28a00297 564 *Interface = NULL;\r
565 Status = EFI_SUCCESS;\r
566\r
567 //\r
568 // Set initial position\r
569 //\r
570 Position.Protocol = Protocol;\r
571 Position.SearchKey = Registration;\r
572 Position.Position = &gHandleList;\r
022c6d45 573\r
28a00297 574 //\r
575 // Lock the protocol database\r
576 //\r
577 CoreAcquireProtocolLock ();\r
578\r
579 mEfiLocateHandleRequest += 1;\r
580\r
e94a9ff7 581 if (Registration == NULL) {\r
28a00297 582 //\r
583 // Look up the protocol entry and set the head pointer\r
584 //\r
585 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
586 if (Position.ProtEntry == NULL) {\r
587 Status = EFI_NOT_FOUND;\r
588 goto Done;\r
589 }\r
590 Position.Position = &Position.ProtEntry->Protocols;\r
591\r
592 Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
593 } else {\r
022c6d45 594 Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);\r
28a00297 595 }\r
596\r
e94a9ff7 597 if (Handle == NULL) {\r
28a00297 598 Status = EFI_NOT_FOUND;\r
e94a9ff7 599 } else if (Registration != NULL) {\r
28a00297 600 //\r
601 // If this is a search by register notify and a handle was\r
602 // returned, update the register notification position\r
022c6d45 603 //\r
28a00297 604 ProtNotify = Registration;\r
605 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
606 }\r
607\r
608Done:\r
609 CoreReleaseProtocolLock ();\r
610 return Status;\r
611}\r
612\r
613\r
162ed594 614/**\r
615 Function returns an array of handles that support the requested protocol\r
616 in a buffer allocated from pool. This is a version of CoreLocateHandle()\r
617 that allocates a buffer for the caller.\r
618\r
022c6d45 619 @param SearchType Specifies which handle(s) are to be returned.\r
620 @param Protocol Provides the protocol to search by. This\r
621 parameter is only valid for SearchType\r
622 ByProtocol.\r
623 @param SearchKey Supplies the search key depending on the\r
624 SearchType.\r
625 @param NumberHandles The number of handles returned in Buffer.\r
626 @param Buffer A pointer to the buffer to return the requested\r
627 array of handles that support Protocol.\r
628\r
629 @retval EFI_SUCCESS The result array of handles was returned.\r
630 @retval EFI_NOT_FOUND No handles match the search.\r
631 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
632 matching results.\r
e94a9ff7 633 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.\r
162ed594 634\r
635**/\r
28a00297 636EFI_STATUS\r
637EFIAPI\r
638CoreLocateHandleBuffer (\r
639 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
640 IN EFI_GUID *Protocol OPTIONAL,\r
641 IN VOID *SearchKey OPTIONAL,\r
642 IN OUT UINTN *NumberHandles,\r
643 OUT EFI_HANDLE **Buffer\r
644 )\r
28a00297 645{\r
646 EFI_STATUS Status;\r
647 UINTN BufferSize;\r
648\r
649 if (NumberHandles == NULL) {\r
650 return EFI_INVALID_PARAMETER;\r
651 }\r
652\r
653 if (Buffer == NULL) {\r
654 return EFI_INVALID_PARAMETER;\r
655 }\r
656\r
657 BufferSize = 0;\r
658 *NumberHandles = 0;\r
659 *Buffer = NULL;\r
660 Status = CoreLocateHandle (\r
661 SearchType,\r
662 Protocol,\r
663 SearchKey,\r
664 &BufferSize,\r
665 *Buffer\r
666 );\r
667 //\r
668 // LocateHandleBuffer() returns incorrect status code if SearchType is\r
669 // invalid.\r
670 //\r
671 // Add code to correctly handle expected errors from CoreLocateHandle().\r
672 //\r
673 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
674 if (Status != EFI_INVALID_PARAMETER) {\r
675 Status = EFI_NOT_FOUND;\r
676 }\r
677 return Status;\r
678 }\r
679\r
9c4ac31c 680 *Buffer = AllocatePool (BufferSize);\r
28a00297 681 if (*Buffer == NULL) {\r
682 return EFI_OUT_OF_RESOURCES;\r
683 }\r
684\r
685 Status = CoreLocateHandle (\r
686 SearchType,\r
687 Protocol,\r
688 SearchKey,\r
689 &BufferSize,\r
690 *Buffer\r
691 );\r
692\r
e94a9ff7 693 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
28a00297 694 if (EFI_ERROR(Status)) {\r
695 *NumberHandles = 0;\r
696 }\r
697\r
698 return Status;\r
699}\r
700\r
701\r
162ed594 702\r