]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Locate.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Locate.c
CommitLineData
23c98c94 1/** @file\r
2 Locate handle functions\r
28a00297 3\r
d1102dba 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
28a00297 6\r
504214c4 7**/\r
28a00297 8\r
9c4ac31c 9#include "DxeMain.h"\r
ec90508b 10#include "Handle.h"\r
28a00297 11\r
12//\r
13// ProtocolRequest - Last LocateHandle request ID\r
14//\r
15UINTN mEfiLocateHandleRequest = 0;\r
16\r
17//\r
18// Internal prototypes\r
19//\r
20\r
21typedef struct {\r
22 EFI_GUID *Protocol;\r
23 VOID *SearchKey;\r
24 LIST_ENTRY *Position;\r
25 PROTOCOL_ENTRY *ProtEntry;\r
26} LOCATE_POSITION;\r
27\r
022c6d45 28typedef\r
28a00297 29IHANDLE *\r
30(* CORE_GET_NEXT) (\r
31 IN OUT LOCATE_POSITION *Position,\r
32 OUT VOID **Interface\r
33 );\r
34\r
162ed594 35/**\r
36 Routine to get the next Handle, when you are searching for all handles.\r
37\r
022c6d45 38 @param Position Information about which Handle to seach for.\r
39 @param Interface Return the interface structure for the matching\r
40 protocol.\r
162ed594 41\r
022c6d45 42 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 43 Otherwise,NULL is returned.\r
162ed594 44\r
45**/\r
28a00297 46IHANDLE *\r
47CoreGetNextLocateAllHandles (\r
48 IN OUT LOCATE_POSITION *Position,\r
49 OUT VOID **Interface\r
50 );\r
51\r
162ed594 52/**\r
53 Routine to get the next Handle, when you are searching for register protocol\r
54 notifies.\r
55\r
022c6d45 56 @param Position Information about which Handle to seach for.\r
57 @param Interface Return the interface structure for the matching\r
58 protocol.\r
162ed594 59\r
022c6d45 60 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 61 Otherwise,NULL is returned.\r
162ed594 62\r
63**/\r
28a00297 64IHANDLE *\r
65CoreGetNextLocateByRegisterNotify (\r
66 IN OUT LOCATE_POSITION *Position,\r
67 OUT VOID **Interface\r
68 );\r
69\r
162ed594 70/**\r
71 Routine to get the next Handle, when you are searching for a given protocol.\r
72\r
022c6d45 73 @param Position Information about which Handle to seach for.\r
74 @param Interface Return the interface structure for the matching\r
75 protocol.\r
162ed594 76\r
022c6d45 77 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 78 Otherwise,NULL is returned.\r
162ed594 79\r
80**/\r
28a00297 81IHANDLE *\r
82CoreGetNextLocateByProtocol (\r
83 IN OUT LOCATE_POSITION *Position,\r
84 OUT VOID **Interface\r
85 );\r
86\r
28a00297 87\r
162ed594 88/**\r
89 Locates the requested handle(s) and returns them in Buffer.\r
90\r
022c6d45 91 @param SearchType The type of search to perform to locate the\r
92 handles\r
93 @param Protocol The protocol to search for\r
94 @param SearchKey Dependant on SearchType\r
95 @param BufferSize On input the size of Buffer. On output the\r
96 size of data returned.\r
97 @param Buffer The buffer to return the results in\r
98\r
99 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is\r
100 returned in BufferSize.\r
101 @retval EFI_INVALID_PARAMETER Invalid parameter\r
102 @retval EFI_SUCCESS Successfully found the requested handle(s) and\r
162ed594 103 returns them in Buffer.\r
28a00297 104\r
162ed594 105**/\r
28a00297 106EFI_STATUS\r
107EFIAPI\r
108CoreLocateHandle (\r
109 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
110 IN EFI_GUID *Protocol OPTIONAL,\r
111 IN VOID *SearchKey OPTIONAL,\r
112 IN OUT UINTN *BufferSize,\r
113 OUT EFI_HANDLE *Buffer\r
114 )\r
28a00297 115{\r
116 EFI_STATUS Status;\r
117 LOCATE_POSITION Position;\r
118 PROTOCOL_NOTIFY *ProtNotify;\r
119 CORE_GET_NEXT GetNext;\r
120 UINTN ResultSize;\r
121 IHANDLE *Handle;\r
122 IHANDLE **ResultBuffer;\r
123 VOID *Interface;\r
022c6d45 124\r
28a00297 125 if (BufferSize == NULL) {\r
29dd3b04 126 return EFI_INVALID_PARAMETER;\r
28a00297 127 }\r
022c6d45 128\r
28a00297 129 if ((*BufferSize > 0) && (Buffer == NULL)) {\r
130 return EFI_INVALID_PARAMETER;\r
131 }\r
022c6d45 132\r
28a00297 133 GetNext = NULL;\r
e94a9ff7 134\r
28a00297 135 //\r
136 // Set initial position\r
137 //\r
28a00297 138 Position.Protocol = Protocol;\r
139 Position.SearchKey = SearchKey;\r
140 Position.Position = &gHandleList;\r
141\r
142 ResultSize = 0;\r
143 ResultBuffer = (IHANDLE **) Buffer;\r
144 Status = EFI_SUCCESS;\r
145\r
146 //\r
147 // Lock the protocol database\r
148 //\r
28a00297 149 CoreAcquireProtocolLock ();\r
150\r
151 //\r
152 // Get the search function based on type\r
153 //\r
154 switch (SearchType) {\r
022c6d45 155 case AllHandles:\r
156 GetNext = CoreGetNextLocateAllHandles;\r
28a00297 157 break;\r
158\r
022c6d45 159 case ByRegisterNotify:\r
28a00297 160 //\r
161 // Must have SearchKey for locate ByRegisterNotify\r
162 //\r
163 if (SearchKey == NULL) {\r
164 Status = EFI_INVALID_PARAMETER;\r
165 break;\r
166 }\r
022c6d45 167 GetNext = CoreGetNextLocateByRegisterNotify;\r
28a00297 168 break;\r
169\r
022c6d45 170 case ByProtocol:\r
28a00297 171 GetNext = CoreGetNextLocateByProtocol;\r
172 if (Protocol == NULL) {\r
173 Status = EFI_INVALID_PARAMETER;\r
174 break;\r
175 }\r
176 //\r
177 // Look up the protocol entry and set the head pointer\r
178 //\r
179 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
180 if (Position.ProtEntry == NULL) {\r
181 Status = EFI_NOT_FOUND;\r
182 break;\r
183 }\r
184 Position.Position = &Position.ProtEntry->Protocols;\r
185 break;\r
186\r
187 default:\r
188 Status = EFI_INVALID_PARAMETER;\r
189 break;\r
190 }\r
191\r
192 if (EFI_ERROR(Status)) {\r
193 CoreReleaseProtocolLock ();\r
194 return Status;\r
195 }\r
196\r
d2fbaaab 197 ASSERT (GetNext != NULL);\r
28a00297 198 //\r
199 // Enumerate out the matching handles\r
200 //\r
201 mEfiLocateHandleRequest += 1;\r
202 for (; ;) {\r
203 //\r
204 // Get the next handle. If no more handles, stop\r
205 //\r
206 Handle = GetNext (&Position, &Interface);\r
207 if (NULL == Handle) {\r
208 break;\r
209 }\r
210\r
211 //\r
212 // Increase the resulting buffer size, and if this handle\r
213 // fits return it\r
214 //\r
215 ResultSize += sizeof(Handle);\r
216 if (ResultSize <= *BufferSize) {\r
217 *ResultBuffer = Handle;\r
218 ResultBuffer += 1;\r
219 }\r
220 }\r
221\r
222 //\r
223 // If the result is a zero length buffer, then there were no\r
224 // matching handles\r
225 //\r
226 if (ResultSize == 0) {\r
227 Status = EFI_NOT_FOUND;\r
228 } else {\r
229 //\r
230 // Return the resulting buffer size. If it's larger than what\r
231 // was passed, then set the error code\r
232 //\r
233 if (ResultSize > *BufferSize) {\r
234 Status = EFI_BUFFER_TOO_SMALL;\r
022c6d45 235 }\r
236\r
28a00297 237 *BufferSize = ResultSize;\r
238\r
239 if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {\r
240 //\r
241 // If this is a search by register notify and a handle was\r
242 // returned, update the register notification position\r
022c6d45 243 //\r
d2fbaaab 244 ASSERT (SearchKey != NULL);\r
28a00297 245 ProtNotify = SearchKey;\r
246 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
247 }\r
248 }\r
249\r
250 CoreReleaseProtocolLock ();\r
251 return Status;\r
252}\r
253\r
254\r
162ed594 255\r
256/**\r
257 Routine to get the next Handle, when you are searching for all handles.\r
258\r
022c6d45 259 @param Position Information about which Handle to seach for.\r
260 @param Interface Return the interface structure for the matching\r
261 protocol.\r
162ed594 262\r
e94a9ff7 263 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 264 Otherwise,NULL is returned.\r
162ed594 265\r
266**/\r
28a00297 267IHANDLE *\r
268CoreGetNextLocateAllHandles (\r
269 IN OUT LOCATE_POSITION *Position,\r
270 OUT VOID **Interface\r
271 )\r
28a00297 272{\r
273 IHANDLE *Handle;\r
274\r
275 //\r
276 // Next handle\r
277 //\r
278 Position->Position = Position->Position->ForwardLink;\r
279\r
280 //\r
281 // If not at the end of the list, get the handle\r
282 //\r
4008328a 283 Handle = NULL;\r
28a00297 284 *Interface = NULL;\r
285 if (Position->Position != &gHandleList) {\r
286 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
287 }\r
288\r
289 return Handle;\r
290}\r
291\r
292\r
162ed594 293\r
294/**\r
295 Routine to get the next Handle, when you are searching for register protocol\r
296 notifies.\r
297\r
022c6d45 298 @param Position Information about which Handle to seach for.\r
299 @param Interface Return the interface structure for the matching\r
300 protocol.\r
162ed594 301\r
e94a9ff7 302 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 303 Otherwise,NULL is returned.\r
162ed594 304\r
305**/\r
28a00297 306IHANDLE *\r
307CoreGetNextLocateByRegisterNotify (\r
308 IN OUT LOCATE_POSITION *Position,\r
309 OUT VOID **Interface\r
310 )\r
28a00297 311{\r
312 IHANDLE *Handle;\r
313 PROTOCOL_NOTIFY *ProtNotify;\r
314 PROTOCOL_INTERFACE *Prot;\r
022c6d45 315 LIST_ENTRY *Link;\r
28a00297 316\r
4008328a 317 Handle = NULL;\r
28a00297 318 *Interface = NULL;\r
319 ProtNotify = Position->SearchKey;\r
320\r
321 //\r
322 // If this is the first request, get the next handle\r
323 //\r
324 if (ProtNotify != NULL) {\r
325 ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
326 Position->SearchKey = NULL;\r
327\r
328 //\r
329 // If not at the end of the list, get the next handle\r
330 //\r
331 Link = ProtNotify->Position->ForwardLink;\r
332 if (Link != &ProtNotify->Protocol->Protocols) {\r
333 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 334 Handle = Prot->Handle;\r
28a00297 335 *Interface = Prot->Interface;\r
022c6d45 336 }\r
28a00297 337 }\r
338\r
339 return Handle;\r
340}\r
341\r
342\r
162ed594 343/**\r
344 Routine to get the next Handle, when you are searching for a given protocol.\r
345\r
022c6d45 346 @param Position Information about which Handle to seach for.\r
347 @param Interface Return the interface structure for the matching\r
348 protocol.\r
162ed594 349\r
e94a9ff7 350 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 351 Otherwise,NULL is returned.\r
162ed594 352\r
353**/\r
28a00297 354IHANDLE *\r
355CoreGetNextLocateByProtocol (\r
356 IN OUT LOCATE_POSITION *Position,\r
357 OUT VOID **Interface\r
358 )\r
28a00297 359{\r
360 IHANDLE *Handle;\r
361 LIST_ENTRY *Link;\r
362 PROTOCOL_INTERFACE *Prot;\r
022c6d45 363\r
4008328a 364 Handle = NULL;\r
28a00297 365 *Interface = NULL;\r
366 for (; ;) {\r
367 //\r
368 // Next entry\r
369 //\r
370 Link = Position->Position->ForwardLink;\r
371 Position->Position = Link;\r
372\r
373 //\r
374 // If not at the end, return the handle\r
375 //\r
376 if (Link == &Position->ProtEntry->Protocols) {\r
4008328a 377 Handle = NULL;\r
28a00297 378 break;\r
379 }\r
380\r
381 //\r
382 // Get the handle\r
383 //\r
384 Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 385 Handle = Prot->Handle;\r
28a00297 386 *Interface = Prot->Interface;\r
387\r
388 //\r
022c6d45 389 // If this handle has not been returned this request, then\r
28a00297 390 // return it now\r
391 //\r
392 if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
393 Handle->LocateRequest = mEfiLocateHandleRequest;\r
394 break;\r
395 }\r
396 }\r
397\r
398 return Handle;\r
399}\r
400\r
401\r
162ed594 402/**\r
a36a9b37 403 Locates the handle to a device on the device path that supports the specified protocol.\r
162ed594 404\r
a36a9b37 405 @param Protocol Specifies the protocol to search for.\r
406 @param DevicePath On input, a pointer to a pointer to the device path. On output, the device\r
407 path pointer is modified to point to the remaining part of the device\r
408 path.\r
409 @param Device A pointer to the returned device handle.\r
162ed594 410\r
a36a9b37 411 @retval EFI_SUCCESS The resulting handle was returned.\r
412 @retval EFI_NOT_FOUND No handles match the search.\r
413 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
414 @retval EFI_INVALID_PARAMETER DevicePath is NULL.\r
415 @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.\r
162ed594 416\r
417**/\r
28a00297 418EFI_STATUS\r
419EFIAPI\r
420CoreLocateDevicePath (\r
421 IN EFI_GUID *Protocol,\r
422 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
423 OUT EFI_HANDLE *Device\r
424 )\r
28a00297 425{\r
426 INTN SourceSize;\r
427 INTN Size;\r
428 INTN BestMatch;\r
429 UINTN HandleCount;\r
430 UINTN Index;\r
431 EFI_STATUS Status;\r
432 EFI_HANDLE *Handles;\r
433 EFI_HANDLE Handle;\r
a36a9b37 434 EFI_HANDLE BestDevice;\r
28a00297 435 EFI_DEVICE_PATH_PROTOCOL *SourcePath;\r
436 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
022c6d45 437\r
28a00297 438 if (Protocol == NULL) {\r
439 return EFI_INVALID_PARAMETER;\r
440 }\r
022c6d45 441\r
28a00297 442 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
443 return EFI_INVALID_PARAMETER;\r
444 }\r
022c6d45 445\r
4e1005ec 446 Handles = NULL;\r
a36a9b37 447 BestDevice = NULL;\r
28a00297 448 SourcePath = *DevicePath;\r
dc07b3d5 449 TmpDevicePath = SourcePath;\r
450 while (!IsDevicePathEnd (TmpDevicePath)) {\r
451 if (IsDevicePathEndInstance (TmpDevicePath)) {\r
452 //\r
453 // If DevicePath is a multi-instance device path,\r
d1102dba 454 // the function will operate on the first instance\r
dc07b3d5 455 //\r
456 break;\r
457 }\r
458 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
459 }\r
460\r
461 SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;\r
022c6d45 462\r
28a00297 463 //\r
464 // Get a list of all handles that support the requested protocol\r
465 //\r
466 Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
467 if (EFI_ERROR (Status) || HandleCount == 0) {\r
468 return EFI_NOT_FOUND;\r
469 }\r
470\r
471 BestMatch = -1;\r
472 for(Index = 0; Index < HandleCount; Index += 1) {\r
473 Handle = Handles[Index];\r
474 Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
475 if (EFI_ERROR (Status)) {\r
476 //\r
477 // If this handle doesn't support device path, then skip it\r
478 //\r
479 continue;\r
480 }\r
481\r
482 //\r
483 // Check if DevicePath is first part of SourcePath\r
484 //\r
9c4ac31c 485 Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
cd7bfc2c
ED
486 ASSERT (Size >= 0);\r
487 if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, (UINTN) Size) == 0) {\r
28a00297 488 //\r
489 // If the size is equal to the best match, then we\r
dc07b3d5 490 // have a duplicate device path for 2 different device\r
28a00297 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
a36a9b37 500 BestDevice = Handle;\r
28a00297 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
a36a9b37 515 if (Device == NULL) {\r
516 return EFI_INVALID_PARAMETER;\r
517 }\r
518 *Device = BestDevice;\r
d1102dba 519\r
28a00297 520 //\r
521 // Return the remaining part of the device path\r
522 //\r
523 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
524 return EFI_SUCCESS;\r
525}\r
526\r
527\r
44310938 528/**\r
28a00297 529 Return the first Protocol Interface that matches the Protocol GUID. If\r
8bc18cc6 530 Registration is passed in, return a Protocol Instance that was just add\r
531 to the system. If Registration is NULL return the first Protocol Interface\r
28a00297 532 you find.\r
533\r
022c6d45 534 @param Protocol The protocol to search for\r
535 @param Registration Optional Registration Key returned from\r
536 RegisterProtocolNotify()\r
537 @param Interface Return the Protocol interface (instance).\r
28a00297 538\r
022c6d45 539 @retval EFI_SUCCESS If a valid Interface is returned\r
540 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 541 @retval EFI_NOT_FOUND Protocol interface not found\r
28a00297 542\r
162ed594 543**/\r
544EFI_STATUS\r
545EFIAPI\r
546CoreLocateProtocol (\r
547 IN EFI_GUID *Protocol,\r
548 IN VOID *Registration OPTIONAL,\r
549 OUT VOID **Interface\r
550 )\r
28a00297 551{\r
552 EFI_STATUS Status;\r
553 LOCATE_POSITION Position;\r
554 PROTOCOL_NOTIFY *ProtNotify;\r
555 IHANDLE *Handle;\r
556\r
415fc5e5 557 if ((Interface == NULL) || (Protocol == NULL)) {\r
28a00297 558 return EFI_INVALID_PARAMETER;\r
559 }\r
022c6d45 560\r
28a00297 561 *Interface = NULL;\r
562 Status = EFI_SUCCESS;\r
563\r
564 //\r
565 // Set initial position\r
566 //\r
567 Position.Protocol = Protocol;\r
568 Position.SearchKey = Registration;\r
569 Position.Position = &gHandleList;\r
022c6d45 570\r
28a00297 571 //\r
572 // Lock the protocol database\r
573 //\r
ae6945b6
RN
574 Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock);\r
575 if (EFI_ERROR (Status)) {\r
576 return EFI_NOT_FOUND;\r
577 }\r
28a00297 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
6393d9c8 633 @retval EFI_INVALID_PARAMETER One or more parameters 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