]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - 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
1/** @file\r
2 Locate handle functions\r
3\r
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
9\r
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
12\r
13**/\r
14\r
15#include "DxeMain.h"\r
16#include "Handle.h"\r
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
34typedef\r
35IHANDLE *\r
36(* CORE_GET_NEXT) (\r
37 IN OUT LOCATE_POSITION *Position,\r
38 OUT VOID **Interface\r
39 );\r
40\r
41/**\r
42 Routine to get the next Handle, when you are searching for all handles.\r
43\r
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
47\r
48 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
49 Otherwise,NULL is returned.\r
50\r
51**/\r
52IHANDLE *\r
53CoreGetNextLocateAllHandles (\r
54 IN OUT LOCATE_POSITION *Position,\r
55 OUT VOID **Interface\r
56 );\r
57\r
58/**\r
59 Routine to get the next Handle, when you are searching for register protocol\r
60 notifies.\r
61\r
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
65\r
66 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
67 Otherwise,NULL is returned.\r
68\r
69**/\r
70IHANDLE *\r
71CoreGetNextLocateByRegisterNotify (\r
72 IN OUT LOCATE_POSITION *Position,\r
73 OUT VOID **Interface\r
74 );\r
75\r
76/**\r
77 Routine to get the next Handle, when you are searching for a given protocol.\r
78\r
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
82\r
83 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
84 Otherwise,NULL is returned.\r
85\r
86**/\r
87IHANDLE *\r
88CoreGetNextLocateByProtocol (\r
89 IN OUT LOCATE_POSITION *Position,\r
90 OUT VOID **Interface\r
91 );\r
92\r
93\r
94/**\r
95 Locates the requested handle(s) and returns them in Buffer.\r
96\r
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
109 returns them in Buffer.\r
110\r
111**/\r
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
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
130\r
131 if (BufferSize == NULL) {\r
132 return EFI_INVALID_PARAMETER;\r
133 }\r
134\r
135 if ((*BufferSize > 0) && (Buffer == NULL)) {\r
136 return EFI_INVALID_PARAMETER;\r
137 }\r
138\r
139 GetNext = NULL;\r
140\r
141 //\r
142 // Set initial position\r
143 //\r
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
155 CoreAcquireProtocolLock ();\r
156\r
157 //\r
158 // Get the search function based on type\r
159 //\r
160 switch (SearchType) {\r
161 case AllHandles:\r
162 GetNext = CoreGetNextLocateAllHandles;\r
163 break;\r
164\r
165 case ByRegisterNotify:\r
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
173 GetNext = CoreGetNextLocateByRegisterNotify;\r
174 break;\r
175\r
176 case ByProtocol:\r
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
240 }\r
241\r
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
248 //\r
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
259\r
260/**\r
261 Routine to get the next Handle, when you are searching for all handles.\r
262\r
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
266\r
267 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
268 Otherwise,NULL is returned.\r
269\r
270**/\r
271IHANDLE *\r
272CoreGetNextLocateAllHandles (\r
273 IN OUT LOCATE_POSITION *Position,\r
274 OUT VOID **Interface\r
275 )\r
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
287 Handle = NULL;\r
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
297\r
298/**\r
299 Routine to get the next Handle, when you are searching for register protocol\r
300 notifies.\r
301\r
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
305\r
306 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
307 Otherwise,NULL is returned.\r
308\r
309**/\r
310IHANDLE *\r
311CoreGetNextLocateByRegisterNotify (\r
312 IN OUT LOCATE_POSITION *Position,\r
313 OUT VOID **Interface\r
314 )\r
315{\r
316 IHANDLE *Handle;\r
317 PROTOCOL_NOTIFY *ProtNotify;\r
318 PROTOCOL_INTERFACE *Prot;\r
319 LIST_ENTRY *Link;\r
320\r
321 Handle = NULL;\r
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
338 Handle = Prot->Handle;\r
339 *Interface = Prot->Interface;\r
340 }\r
341 }\r
342\r
343 return Handle;\r
344}\r
345\r
346\r
347/**\r
348 Routine to get the next Handle, when you are searching for a given protocol.\r
349\r
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
353\r
354 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
355 Otherwise,NULL is returned.\r
356\r
357**/\r
358IHANDLE *\r
359CoreGetNextLocateByProtocol (\r
360 IN OUT LOCATE_POSITION *Position,\r
361 OUT VOID **Interface\r
362 )\r
363{\r
364 IHANDLE *Handle;\r
365 LIST_ENTRY *Link;\r
366 PROTOCOL_INTERFACE *Prot;\r
367\r
368 Handle = NULL;\r
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
381 Handle = NULL;\r
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
389 Handle = Prot->Handle;\r
390 *Interface = Prot->Interface;\r
391\r
392 //\r
393 // If this handle has not been returned this request, then\r
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
406/**\r
407 Locates the handle to a device on the device path that best matches the specified protocol.\r
408\r
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
415\r
416 @retval EFI_SUCCESS The resulting handle was returned.\r
417 @retval EFI_NOT_FOUND No handles matched the search.\r
418 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
419\r
420**/\r
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
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
439\r
440 if (Protocol == NULL) {\r
441 return EFI_INVALID_PARAMETER;\r
442 }\r
443\r
444 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
445 return EFI_INVALID_PARAMETER;\r
446 }\r
447\r
448 if (Device == NULL) {\r
449 return EFI_INVALID_PARAMETER;\r
450 }\r
451\r
452 *Device = NULL;\r
453 SourcePath = *DevicePath;\r
454 SourceSize = GetDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
455\r
456 //\r
457 // The source path can only have 1 instance\r
458 //\r
459 if (IsDevicePathMultiInstance (SourcePath)) {\r
460 DEBUG((DEBUG_ERROR, "LocateDevicePath: Device path has too many instances\n"));\r
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
486 Size = GetDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
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
494\r
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
506\r
507 //\r
508 // If there wasn't any match, then no parts of the device path was found.\r
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
523/**\r
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
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
533\r
534 @retval EFI_SUCCESS If a valid Interface is returned\r
535 @retval EFI_INVALID_PARAMETER Invalid parameter\r
536 @retval EFI_NOT_FOUND Protocol interface not found\r
537\r
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
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
555\r
556 if (Protocol == NULL) {\r
557 return EFI_NOT_FOUND;\r
558 }\r
559\r
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
569\r
570 //\r
571 // Lock the protocol database\r
572 //\r
573 CoreAcquireProtocolLock ();\r
574\r
575 mEfiLocateHandleRequest += 1;\r
576\r
577 if (Registration == NULL) {\r
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
590 Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface);\r
591 }\r
592\r
593 if (Handle == NULL) {\r
594 Status = EFI_NOT_FOUND;\r
595 } else if (Registration != NULL) {\r
596 //\r
597 // If this is a search by register notify and a handle was\r
598 // returned, update the register notification position\r
599 //\r
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
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
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
629 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.\r
630\r
631**/\r
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
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
676 *Buffer = AllocatePool (BufferSize);\r
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
689 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
690 if (EFI_ERROR(Status)) {\r
691 *NumberHandles = 0;\r
692 }\r
693\r
694 return Status;\r
695}\r
696\r
697\r
698\r