]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Locate.c
MdeModulePkg/Core/Dxe: Acquire a lock when iterating gHandleList
[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
5ece2ad3
HM
89 Internal function for locating the requested handle(s) and returns them in Buffer.\r
90 The caller should already have acquired the ProtocolLock.\r
162ed594 91\r
022c6d45 92 @param SearchType The type of search to perform to locate the\r
93 handles\r
94 @param Protocol The protocol to search for\r
95 @param SearchKey Dependant on SearchType\r
96 @param BufferSize On input the size of Buffer. On output the\r
97 size of data returned.\r
98 @param Buffer The buffer to return the results in\r
99\r
100 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is\r
101 returned in BufferSize.\r
102 @retval EFI_INVALID_PARAMETER Invalid parameter\r
103 @retval EFI_SUCCESS Successfully found the requested handle(s) and\r
162ed594 104 returns them in Buffer.\r
28a00297 105\r
162ed594 106**/\r
28a00297 107EFI_STATUS\r
5ece2ad3 108InternalCoreLocateHandle (\r
28a00297 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
28a00297 146 //\r
147 // Get the search function based on type\r
148 //\r
149 switch (SearchType) {\r
022c6d45 150 case AllHandles:\r
151 GetNext = CoreGetNextLocateAllHandles;\r
28a00297 152 break;\r
153\r
022c6d45 154 case ByRegisterNotify:\r
28a00297 155 //\r
156 // Must have SearchKey for locate ByRegisterNotify\r
157 //\r
158 if (SearchKey == NULL) {\r
159 Status = EFI_INVALID_PARAMETER;\r
160 break;\r
161 }\r
022c6d45 162 GetNext = CoreGetNextLocateByRegisterNotify;\r
28a00297 163 break;\r
164\r
022c6d45 165 case ByProtocol:\r
28a00297 166 GetNext = CoreGetNextLocateByProtocol;\r
167 if (Protocol == NULL) {\r
168 Status = EFI_INVALID_PARAMETER;\r
169 break;\r
170 }\r
171 //\r
172 // Look up the protocol entry and set the head pointer\r
173 //\r
174 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
175 if (Position.ProtEntry == NULL) {\r
176 Status = EFI_NOT_FOUND;\r
177 break;\r
178 }\r
179 Position.Position = &Position.ProtEntry->Protocols;\r
180 break;\r
181\r
182 default:\r
183 Status = EFI_INVALID_PARAMETER;\r
184 break;\r
185 }\r
186\r
187 if (EFI_ERROR(Status)) {\r
28a00297 188 return Status;\r
189 }\r
190\r
d2fbaaab 191 ASSERT (GetNext != NULL);\r
28a00297 192 //\r
193 // Enumerate out the matching handles\r
194 //\r
195 mEfiLocateHandleRequest += 1;\r
196 for (; ;) {\r
197 //\r
198 // Get the next handle. If no more handles, stop\r
199 //\r
200 Handle = GetNext (&Position, &Interface);\r
201 if (NULL == Handle) {\r
202 break;\r
203 }\r
204\r
205 //\r
206 // Increase the resulting buffer size, and if this handle\r
207 // fits return it\r
208 //\r
209 ResultSize += sizeof(Handle);\r
210 if (ResultSize <= *BufferSize) {\r
211 *ResultBuffer = Handle;\r
212 ResultBuffer += 1;\r
213 }\r
214 }\r
215\r
216 //\r
217 // If the result is a zero length buffer, then there were no\r
218 // matching handles\r
219 //\r
220 if (ResultSize == 0) {\r
221 Status = EFI_NOT_FOUND;\r
222 } else {\r
223 //\r
224 // Return the resulting buffer size. If it's larger than what\r
225 // was passed, then set the error code\r
226 //\r
227 if (ResultSize > *BufferSize) {\r
228 Status = EFI_BUFFER_TOO_SMALL;\r
022c6d45 229 }\r
230\r
28a00297 231 *BufferSize = ResultSize;\r
232\r
233 if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {\r
234 //\r
235 // If this is a search by register notify and a handle was\r
236 // returned, update the register notification position\r
022c6d45 237 //\r
d2fbaaab 238 ASSERT (SearchKey != NULL);\r
28a00297 239 ProtNotify = SearchKey;\r
240 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
241 }\r
242 }\r
243\r
28a00297 244 return Status;\r
245}\r
246\r
5ece2ad3
HM
247/**\r
248 Locates the requested handle(s) and returns them in Buffer.\r
249\r
250 @param SearchType The type of search to perform to locate the\r
251 handles\r
252 @param Protocol The protocol to search for\r
253 @param SearchKey Dependant on SearchType\r
254 @param BufferSize On input the size of Buffer. On output the\r
255 size of data returned.\r
256 @param Buffer The buffer to return the results in\r
257\r
258 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is\r
259 returned in BufferSize.\r
260 @retval EFI_INVALID_PARAMETER Invalid parameter\r
261 @retval EFI_SUCCESS Successfully found the requested handle(s) and\r
262 returns them in Buffer.\r
263\r
264**/\r
265EFI_STATUS\r
266EFIAPI\r
267CoreLocateHandle (\r
268 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
269 IN EFI_GUID *Protocol OPTIONAL,\r
270 IN VOID *SearchKey OPTIONAL,\r
271 IN OUT UINTN *BufferSize,\r
272 OUT EFI_HANDLE *Buffer\r
273 )\r
274{\r
275 EFI_STATUS Status;\r
276\r
277 //\r
278 // Lock the protocol database\r
279 //\r
280 CoreAcquireProtocolLock ();\r
281 Status = InternalCoreLocateHandle(SearchType, Protocol, SearchKey, BufferSize, Buffer);\r
282 CoreReleaseProtocolLock ();\r
283 return Status;\r
284}\r
28a00297 285\r
162ed594 286\r
287/**\r
288 Routine to get the next Handle, when you are searching for all handles.\r
289\r
022c6d45 290 @param Position Information about which Handle to seach for.\r
291 @param Interface Return the interface structure for the matching\r
292 protocol.\r
162ed594 293\r
e94a9ff7 294 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 295 Otherwise,NULL is returned.\r
162ed594 296\r
297**/\r
28a00297 298IHANDLE *\r
299CoreGetNextLocateAllHandles (\r
300 IN OUT LOCATE_POSITION *Position,\r
301 OUT VOID **Interface\r
302 )\r
28a00297 303{\r
304 IHANDLE *Handle;\r
305\r
306 //\r
307 // Next handle\r
308 //\r
309 Position->Position = Position->Position->ForwardLink;\r
310\r
311 //\r
312 // If not at the end of the list, get the handle\r
313 //\r
4008328a 314 Handle = NULL;\r
28a00297 315 *Interface = NULL;\r
316 if (Position->Position != &gHandleList) {\r
317 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
318 }\r
319\r
320 return Handle;\r
321}\r
322\r
323\r
162ed594 324\r
325/**\r
326 Routine to get the next Handle, when you are searching for register protocol\r
327 notifies.\r
328\r
022c6d45 329 @param Position Information about which Handle to seach for.\r
330 @param Interface Return the interface structure for the matching\r
331 protocol.\r
162ed594 332\r
e94a9ff7 333 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 334 Otherwise,NULL is returned.\r
162ed594 335\r
336**/\r
28a00297 337IHANDLE *\r
338CoreGetNextLocateByRegisterNotify (\r
339 IN OUT LOCATE_POSITION *Position,\r
340 OUT VOID **Interface\r
341 )\r
28a00297 342{\r
343 IHANDLE *Handle;\r
344 PROTOCOL_NOTIFY *ProtNotify;\r
345 PROTOCOL_INTERFACE *Prot;\r
022c6d45 346 LIST_ENTRY *Link;\r
28a00297 347\r
4008328a 348 Handle = NULL;\r
28a00297 349 *Interface = NULL;\r
350 ProtNotify = Position->SearchKey;\r
351\r
352 //\r
353 // If this is the first request, get the next handle\r
354 //\r
355 if (ProtNotify != NULL) {\r
356 ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
357 Position->SearchKey = NULL;\r
358\r
359 //\r
360 // If not at the end of the list, get the next handle\r
361 //\r
362 Link = ProtNotify->Position->ForwardLink;\r
363 if (Link != &ProtNotify->Protocol->Protocols) {\r
364 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 365 Handle = Prot->Handle;\r
28a00297 366 *Interface = Prot->Interface;\r
022c6d45 367 }\r
28a00297 368 }\r
369\r
370 return Handle;\r
371}\r
372\r
373\r
162ed594 374/**\r
375 Routine to get the next Handle, when you are searching for a given protocol.\r
376\r
022c6d45 377 @param Position Information about which Handle to seach for.\r
378 @param Interface Return the interface structure for the matching\r
379 protocol.\r
162ed594 380\r
e94a9ff7 381 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
4008328a 382 Otherwise,NULL is returned.\r
162ed594 383\r
384**/\r
28a00297 385IHANDLE *\r
386CoreGetNextLocateByProtocol (\r
387 IN OUT LOCATE_POSITION *Position,\r
388 OUT VOID **Interface\r
389 )\r
28a00297 390{\r
391 IHANDLE *Handle;\r
392 LIST_ENTRY *Link;\r
393 PROTOCOL_INTERFACE *Prot;\r
022c6d45 394\r
4008328a 395 Handle = NULL;\r
28a00297 396 *Interface = NULL;\r
397 for (; ;) {\r
398 //\r
399 // Next entry\r
400 //\r
401 Link = Position->Position->ForwardLink;\r
402 Position->Position = Link;\r
403\r
404 //\r
405 // If not at the end, return the handle\r
406 //\r
407 if (Link == &Position->ProtEntry->Protocols) {\r
4008328a 408 Handle = NULL;\r
28a00297 409 break;\r
410 }\r
411\r
412 //\r
413 // Get the handle\r
414 //\r
415 Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
b9066aae 416 Handle = Prot->Handle;\r
28a00297 417 *Interface = Prot->Interface;\r
418\r
419 //\r
022c6d45 420 // If this handle has not been returned this request, then\r
28a00297 421 // return it now\r
422 //\r
423 if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
424 Handle->LocateRequest = mEfiLocateHandleRequest;\r
425 break;\r
426 }\r
427 }\r
428\r
429 return Handle;\r
430}\r
431\r
432\r
162ed594 433/**\r
a36a9b37 434 Locates the handle to a device on the device path that supports the specified protocol.\r
162ed594 435\r
a36a9b37 436 @param Protocol Specifies the protocol to search for.\r
437 @param DevicePath On input, a pointer to a pointer to the device path. On output, the device\r
438 path pointer is modified to point to the remaining part of the device\r
439 path.\r
440 @param Device A pointer to the returned device handle.\r
162ed594 441\r
a36a9b37 442 @retval EFI_SUCCESS The resulting handle was returned.\r
443 @retval EFI_NOT_FOUND No handles match the search.\r
444 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
445 @retval EFI_INVALID_PARAMETER DevicePath is NULL.\r
446 @retval EFI_INVALID_PARAMETER A handle matched the search and Device is NULL.\r
162ed594 447\r
448**/\r
28a00297 449EFI_STATUS\r
450EFIAPI\r
451CoreLocateDevicePath (\r
452 IN EFI_GUID *Protocol,\r
453 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
454 OUT EFI_HANDLE *Device\r
455 )\r
28a00297 456{\r
457 INTN SourceSize;\r
458 INTN Size;\r
459 INTN BestMatch;\r
460 UINTN HandleCount;\r
461 UINTN Index;\r
462 EFI_STATUS Status;\r
463 EFI_HANDLE *Handles;\r
464 EFI_HANDLE Handle;\r
a36a9b37 465 EFI_HANDLE BestDevice;\r
28a00297 466 EFI_DEVICE_PATH_PROTOCOL *SourcePath;\r
467 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
022c6d45 468\r
28a00297 469 if (Protocol == NULL) {\r
470 return EFI_INVALID_PARAMETER;\r
471 }\r
022c6d45 472\r
28a00297 473 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
474 return EFI_INVALID_PARAMETER;\r
475 }\r
022c6d45 476\r
4e1005ec 477 Handles = NULL;\r
a36a9b37 478 BestDevice = NULL;\r
28a00297 479 SourcePath = *DevicePath;\r
dc07b3d5 480 TmpDevicePath = SourcePath;\r
481 while (!IsDevicePathEnd (TmpDevicePath)) {\r
482 if (IsDevicePathEndInstance (TmpDevicePath)) {\r
483 //\r
484 // If DevicePath is a multi-instance device path,\r
d1102dba 485 // the function will operate on the first instance\r
dc07b3d5 486 //\r
487 break;\r
488 }\r
489 TmpDevicePath = NextDevicePathNode (TmpDevicePath);\r
490 }\r
491\r
492 SourceSize = (UINTN) TmpDevicePath - (UINTN) SourcePath;\r
022c6d45 493\r
28a00297 494 //\r
495 // Get a list of all handles that support the requested protocol\r
496 //\r
497 Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
498 if (EFI_ERROR (Status) || HandleCount == 0) {\r
499 return EFI_NOT_FOUND;\r
500 }\r
501\r
502 BestMatch = -1;\r
503 for(Index = 0; Index < HandleCount; Index += 1) {\r
504 Handle = Handles[Index];\r
505 Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
506 if (EFI_ERROR (Status)) {\r
507 //\r
508 // If this handle doesn't support device path, then skip it\r
509 //\r
510 continue;\r
511 }\r
512\r
513 //\r
514 // Check if DevicePath is first part of SourcePath\r
515 //\r
9c4ac31c 516 Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
cd7bfc2c
ED
517 ASSERT (Size >= 0);\r
518 if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, (UINTN) Size) == 0) {\r
28a00297 519 //\r
520 // If the size is equal to the best match, then we\r
dc07b3d5 521 // have a duplicate device path for 2 different device\r
28a00297 522 // handles\r
523 //\r
524 ASSERT (Size != BestMatch);\r
022c6d45 525\r
28a00297 526 //\r
527 // We've got a match, see if it's the best match so far\r
528 //\r
529 if (Size > BestMatch) {\r
530 BestMatch = Size;\r
a36a9b37 531 BestDevice = Handle;\r
28a00297 532 }\r
533 }\r
534 }\r
535\r
536 CoreFreePool (Handles);\r
022c6d45 537\r
28a00297 538 //\r
022c6d45 539 // If there wasn't any match, then no parts of the device path was found.\r
28a00297 540 // Which is strange since there is likely a "root level" device path in the system.\r
541 //\r
542 if (BestMatch == -1) {\r
543 return EFI_NOT_FOUND;\r
544 }\r
545\r
a36a9b37 546 if (Device == NULL) {\r
547 return EFI_INVALID_PARAMETER;\r
548 }\r
549 *Device = BestDevice;\r
d1102dba 550\r
28a00297 551 //\r
552 // Return the remaining part of the device path\r
553 //\r
554 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
555 return EFI_SUCCESS;\r
556}\r
557\r
558\r
44310938 559/**\r
28a00297 560 Return the first Protocol Interface that matches the Protocol GUID. If\r
8bc18cc6 561 Registration is passed in, return a Protocol Instance that was just add\r
562 to the system. If Registration is NULL return the first Protocol Interface\r
28a00297 563 you find.\r
564\r
022c6d45 565 @param Protocol The protocol to search for\r
566 @param Registration Optional Registration Key returned from\r
567 RegisterProtocolNotify()\r
568 @param Interface Return the Protocol interface (instance).\r
28a00297 569\r
022c6d45 570 @retval EFI_SUCCESS If a valid Interface is returned\r
571 @retval EFI_INVALID_PARAMETER Invalid parameter\r
162ed594 572 @retval EFI_NOT_FOUND Protocol interface not found\r
28a00297 573\r
162ed594 574**/\r
575EFI_STATUS\r
576EFIAPI\r
577CoreLocateProtocol (\r
578 IN EFI_GUID *Protocol,\r
579 IN VOID *Registration OPTIONAL,\r
580 OUT VOID **Interface\r
581 )\r
28a00297 582{\r
583 EFI_STATUS Status;\r
584 LOCATE_POSITION Position;\r
585 PROTOCOL_NOTIFY *ProtNotify;\r
586 IHANDLE *Handle;\r
587\r
415fc5e5 588 if ((Interface == NULL) || (Protocol == NULL)) {\r
28a00297 589 return EFI_INVALID_PARAMETER;\r
590 }\r
022c6d45 591\r
28a00297 592 *Interface = NULL;\r
593 Status = EFI_SUCCESS;\r
594\r
595 //\r
596 // Set initial position\r
597 //\r
598 Position.Protocol = Protocol;\r
599 Position.SearchKey = Registration;\r
600 Position.Position = &gHandleList;\r
022c6d45 601\r
28a00297 602 //\r
603 // Lock the protocol database\r
604 //\r
ae6945b6
RN
605 Status = CoreAcquireLockOrFail (&gProtocolDatabaseLock);\r
606 if (EFI_ERROR (Status)) {\r
607 return EFI_NOT_FOUND;\r
608 }\r
28a00297 609\r
610 mEfiLocateHandleRequest += 1;\r
611\r
e94a9ff7 612 if (Registration == NULL) {\r
28a00297 613 //\r
614 // Look up the protocol entry and set the head pointer\r
615 //\r
616 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
617 if (Position.ProtEntry == NULL) {\r
618 Status = EFI_NOT_FOUND;\r
619 goto Done;\r
620 }\r
621 Position.Position = &Position.ProtEntry->Protocols;\r
622\r
623 Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
624 } else {\r
022c6d45 625 Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);\r
28a00297 626 }\r
627\r
e94a9ff7 628 if (Handle == NULL) {\r
28a00297 629 Status = EFI_NOT_FOUND;\r
e94a9ff7 630 } else if (Registration != NULL) {\r
28a00297 631 //\r
632 // If this is a search by register notify and a handle was\r
633 // returned, update the register notification position\r
022c6d45 634 //\r
28a00297 635 ProtNotify = Registration;\r
636 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
637 }\r
638\r
639Done:\r
640 CoreReleaseProtocolLock ();\r
641 return Status;\r
642}\r
643\r
162ed594 644/**\r
645 Function returns an array of handles that support the requested protocol\r
646 in a buffer allocated from pool. This is a version of CoreLocateHandle()\r
647 that allocates a buffer for the caller.\r
648\r
022c6d45 649 @param SearchType Specifies which handle(s) are to be returned.\r
650 @param Protocol Provides the protocol to search by. This\r
651 parameter is only valid for SearchType\r
652 ByProtocol.\r
653 @param SearchKey Supplies the search key depending on the\r
654 SearchType.\r
655 @param NumberHandles The number of handles returned in Buffer.\r
656 @param Buffer A pointer to the buffer to return the requested\r
657 array of handles that support Protocol.\r
658\r
659 @retval EFI_SUCCESS The result array of handles was returned.\r
660 @retval EFI_NOT_FOUND No handles match the search.\r
661 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
662 matching results.\r
6393d9c8 663 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.\r
162ed594 664\r
665**/\r
28a00297 666EFI_STATUS\r
667EFIAPI\r
668CoreLocateHandleBuffer (\r
669 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
670 IN EFI_GUID *Protocol OPTIONAL,\r
671 IN VOID *SearchKey OPTIONAL,\r
672 IN OUT UINTN *NumberHandles,\r
673 OUT EFI_HANDLE **Buffer\r
674 )\r
28a00297 675{\r
676 EFI_STATUS Status;\r
677 UINTN BufferSize;\r
678\r
679 if (NumberHandles == NULL) {\r
680 return EFI_INVALID_PARAMETER;\r
681 }\r
682\r
683 if (Buffer == NULL) {\r
684 return EFI_INVALID_PARAMETER;\r
685 }\r
686\r
687 BufferSize = 0;\r
688 *NumberHandles = 0;\r
689 *Buffer = NULL;\r
5ece2ad3
HM
690\r
691 //\r
692 // Lock the protocol database\r
693 //\r
694 CoreAcquireProtocolLock();\r
695 Status = InternalCoreLocateHandle (\r
28a00297 696 SearchType,\r
697 Protocol,\r
698 SearchKey,\r
699 &BufferSize,\r
700 *Buffer\r
701 );\r
702 //\r
703 // LocateHandleBuffer() returns incorrect status code if SearchType is\r
704 // invalid.\r
705 //\r
706 // Add code to correctly handle expected errors from CoreLocateHandle().\r
707 //\r
708 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
709 if (Status != EFI_INVALID_PARAMETER) {\r
710 Status = EFI_NOT_FOUND;\r
711 }\r
5ece2ad3 712 CoreReleaseProtocolLock ();\r
28a00297 713 return Status;\r
714 }\r
715\r
9c4ac31c 716 *Buffer = AllocatePool (BufferSize);\r
28a00297 717 if (*Buffer == NULL) {\r
5ece2ad3 718 CoreReleaseProtocolLock ();\r
28a00297 719 return EFI_OUT_OF_RESOURCES;\r
720 }\r
721\r
5ece2ad3 722 Status = InternalCoreLocateHandle (\r
28a00297 723 SearchType,\r
724 Protocol,\r
725 SearchKey,\r
726 &BufferSize,\r
727 *Buffer\r
728 );\r
729\r
e94a9ff7 730 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
28a00297 731 if (EFI_ERROR(Status)) {\r
732 *NumberHandles = 0;\r
733 }\r
734\r
5ece2ad3 735 CoreReleaseProtocolLock ();\r
28a00297 736 return Status;\r
737}\r
738\r
739\r
162ed594 740\r