]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/locate.c
Add comments and DoxyGen format for these files.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / locate.c
CommitLineData
504214c4 1/** @file \r
28a00297 2\r
504214c4
LG
3 Locate handle functions \r
4\r
5Copyright (c) 2006 - 2008, Intel Corporation \r
28a00297 6All rights reserved. This program and the accompanying materials \r
7are licensed and made available under the terms and conditions of the BSD License \r
8which accompanies this distribution. The full text of the license may be found at \r
9http://opensource.org/licenses/bsd-license.php \r
10 \r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
504214c4 14**/\r
28a00297 15\r
16#include <DxeMain.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
41STATIC\r
42IHANDLE *\r
43CoreGetNextLocateAllHandles (\r
44 IN OUT LOCATE_POSITION *Position,\r
45 OUT VOID **Interface\r
46 );\r
47\r
48STATIC\r
49IHANDLE *\r
50CoreGetNextLocateByRegisterNotify (\r
51 IN OUT LOCATE_POSITION *Position,\r
52 OUT VOID **Interface\r
53 );\r
54\r
55STATIC\r
56IHANDLE *\r
57CoreGetNextLocateByProtocol (\r
58 IN OUT LOCATE_POSITION *Position,\r
59 OUT VOID **Interface\r
60 );\r
61\r
62//\r
63//\r
64//\r
65\r
66\r
67\r
68 \r
69EFI_STATUS\r
70EFIAPI\r
71CoreLocateHandle (\r
72 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
73 IN EFI_GUID *Protocol OPTIONAL,\r
74 IN VOID *SearchKey OPTIONAL,\r
75 IN OUT UINTN *BufferSize,\r
76 OUT EFI_HANDLE *Buffer\r
77 )\r
78/*++\r
79\r
80Routine Description:\r
81\r
82 Locates the requested handle(s) and returns them in Buffer.\r
83\r
84Arguments:\r
85\r
86 SearchType - The type of search to perform to locate the handles\r
87\r
88 Protocol - The protocol to search for\r
89 \r
90 SearchKey - Dependant on SearchType\r
91\r
92 BufferSize - On input the size of Buffer. On output the \r
93 size of data returned. \r
94\r
95 Buffer - The buffer to return the results in\r
96\r
97\r
98Returns:\r
99\r
100 EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize.\r
101\r
102 EFI_INVALID_PARAMETER - Invalid parameter\r
103 \r
104 EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer.\r
105 \r
106--*/\r
107{\r
108 EFI_STATUS Status;\r
109 LOCATE_POSITION Position;\r
110 PROTOCOL_NOTIFY *ProtNotify;\r
111 CORE_GET_NEXT GetNext;\r
112 UINTN ResultSize;\r
113 IHANDLE *Handle;\r
114 IHANDLE **ResultBuffer;\r
115 VOID *Interface;\r
116 \r
117 if (BufferSize == NULL) {\r
118 Status = EFI_INVALID_PARAMETER;\r
119 }\r
120 \r
121 if ((*BufferSize > 0) && (Buffer == NULL)) {\r
122 return EFI_INVALID_PARAMETER;\r
123 }\r
124 \r
125 GetNext = NULL;\r
126 //\r
127 // Set initial position\r
128 //\r
129\r
130 Position.Protocol = Protocol;\r
131 Position.SearchKey = SearchKey;\r
132 Position.Position = &gHandleList;\r
133\r
134 ResultSize = 0;\r
135 ResultBuffer = (IHANDLE **) Buffer;\r
136 Status = EFI_SUCCESS;\r
137\r
138 //\r
139 // Lock the protocol database\r
140 //\r
141 \r
142 CoreAcquireProtocolLock ();\r
143\r
144 //\r
145 // Get the search function based on type\r
146 //\r
147 switch (SearchType) {\r
148 case AllHandles: \r
149 GetNext = CoreGetNextLocateAllHandles; \r
150 break;\r
151\r
152 case ByRegisterNotify: \r
153 //\r
154 // Must have SearchKey for locate ByRegisterNotify\r
155 //\r
156 if (SearchKey == NULL) {\r
157 Status = EFI_INVALID_PARAMETER;\r
158 break;\r
159 }\r
160 GetNext = CoreGetNextLocateByRegisterNotify; \r
161 break;\r
162\r
163 case ByProtocol: \r
164 GetNext = CoreGetNextLocateByProtocol;\r
165 if (Protocol == NULL) {\r
166 Status = EFI_INVALID_PARAMETER;\r
167 break;\r
168 }\r
169 //\r
170 // Look up the protocol entry and set the head pointer\r
171 //\r
172 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
173 if (Position.ProtEntry == NULL) {\r
174 Status = EFI_NOT_FOUND;\r
175 break;\r
176 }\r
177 Position.Position = &Position.ProtEntry->Protocols;\r
178 break;\r
179\r
180 default:\r
181 Status = EFI_INVALID_PARAMETER;\r
182 break;\r
183 }\r
184\r
185 if (EFI_ERROR(Status)) {\r
186 CoreReleaseProtocolLock ();\r
187 return Status;\r
188 }\r
189\r
190 //\r
191 // Enumerate out the matching handles\r
192 //\r
193 mEfiLocateHandleRequest += 1;\r
194 for (; ;) {\r
195 //\r
196 // Get the next handle. If no more handles, stop\r
197 //\r
198 Handle = GetNext (&Position, &Interface);\r
199 if (NULL == Handle) {\r
200 break;\r
201 }\r
202\r
203 //\r
204 // Increase the resulting buffer size, and if this handle\r
205 // fits return it\r
206 //\r
207 ResultSize += sizeof(Handle);\r
208 if (ResultSize <= *BufferSize) {\r
209 *ResultBuffer = Handle;\r
210 ResultBuffer += 1;\r
211 }\r
212 }\r
213\r
214 //\r
215 // If the result is a zero length buffer, then there were no\r
216 // matching handles\r
217 //\r
218 if (ResultSize == 0) {\r
219 Status = EFI_NOT_FOUND;\r
220 } else {\r
221 //\r
222 // Return the resulting buffer size. If it's larger than what\r
223 // was passed, then set the error code\r
224 //\r
225 if (ResultSize > *BufferSize) {\r
226 Status = EFI_BUFFER_TOO_SMALL;\r
227 } \r
228 \r
229 *BufferSize = ResultSize;\r
230\r
231 if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {\r
232 //\r
233 // If this is a search by register notify and a handle was\r
234 // returned, update the register notification position\r
235 // \r
236 ProtNotify = SearchKey;\r
237 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
238 }\r
239 }\r
240\r
241 CoreReleaseProtocolLock ();\r
242 return Status;\r
243}\r
244\r
245\r
246STATIC\r
247IHANDLE *\r
248CoreGetNextLocateAllHandles (\r
249 IN OUT LOCATE_POSITION *Position,\r
250 OUT VOID **Interface\r
251 )\r
252/*++\r
253\r
254Routine Description:\r
255\r
256 Routine to get the next Handle, when you are searching for all handles.\r
257\r
258Arguments:\r
259\r
260 Position - Information about which Handle to seach for.\r
261\r
262 Interface - Return the interface structure for the matching protocol.\r
263 \r
264Returns:\r
265 IHANDLE - An IHANDLE is returned if the next Position is not the end of the\r
266 list. A NULL_HANDLE is returned if it's the end of the list.\r
267 \r
268--*/\r
269{\r
270 IHANDLE *Handle;\r
271\r
272 //\r
273 // Next handle\r
274 //\r
275 Position->Position = Position->Position->ForwardLink;\r
276\r
277 //\r
278 // If not at the end of the list, get the handle\r
279 //\r
280 Handle = NULL_HANDLE;\r
281 *Interface = NULL;\r
282 if (Position->Position != &gHandleList) {\r
283 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
284 }\r
285\r
286 return Handle;\r
287}\r
288\r
289\r
290STATIC\r
291IHANDLE *\r
292CoreGetNextLocateByRegisterNotify (\r
293 IN OUT LOCATE_POSITION *Position,\r
294 OUT VOID **Interface\r
295 )\r
296/*++\r
297\r
298Routine Description:\r
299\r
300 Routine to get the next Handle, when you are searching for register protocol \r
301 notifies.\r
302\r
303Arguments:\r
304\r
305 Position - Information about which Handle to seach for.\r
306\r
307 Interface - Return the interface structure for the matching protocol.\r
308 \r
309Returns:\r
310 IHANDLE - An IHANDLE is returned if the next Position is not the end of the\r
311 list. A NULL_HANDLE is returned if it's the end of the list.\r
312 \r
313--*/\r
314{\r
315 IHANDLE *Handle;\r
316 PROTOCOL_NOTIFY *ProtNotify;\r
317 PROTOCOL_INTERFACE *Prot;\r
318 LIST_ENTRY *Link; \r
319\r
320 Handle = NULL_HANDLE;\r
321 *Interface = NULL;\r
322 ProtNotify = Position->SearchKey;\r
323\r
324 //\r
325 // If this is the first request, get the next handle\r
326 //\r
327 if (ProtNotify != NULL) {\r
328 ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
329 Position->SearchKey = NULL;\r
330\r
331 //\r
332 // If not at the end of the list, get the next handle\r
333 //\r
334 Link = ProtNotify->Position->ForwardLink;\r
335 if (Link != &ProtNotify->Protocol->Protocols) {\r
336 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
337 Handle = (IHANDLE *) Prot->Handle;\r
338 *Interface = Prot->Interface;\r
339 } \r
340 }\r
341\r
342 return Handle;\r
343}\r
344\r
345\r
346STATIC\r
347IHANDLE *\r
348CoreGetNextLocateByProtocol (\r
349 IN OUT LOCATE_POSITION *Position,\r
350 OUT VOID **Interface\r
351 )\r
352/*++\r
353\r
354Routine Description:\r
355\r
356 Routine to get the next Handle, when you are searching for a given protocol.\r
357\r
358Arguments:\r
359\r
360 Position - Information about which Handle to seach for.\r
361\r
362 Interface - Return the interface structure for the matching protocol.\r
363 \r
364Returns:\r
365 IHANDLE - An IHANDLE is returned if the next Position is not the end of the\r
366 list. A NULL_HANDLE is returned if it's the end of the list.\r
367 \r
368--*/\r
369{\r
370 IHANDLE *Handle;\r
371 LIST_ENTRY *Link;\r
372 PROTOCOL_INTERFACE *Prot;\r
373 \r
374 Handle = NULL_HANDLE;\r
375 *Interface = NULL;\r
376 for (; ;) {\r
377 //\r
378 // Next entry\r
379 //\r
380 Link = Position->Position->ForwardLink;\r
381 Position->Position = Link;\r
382\r
383 //\r
384 // If not at the end, return the handle\r
385 //\r
386 if (Link == &Position->ProtEntry->Protocols) {\r
387 Handle = NULL_HANDLE;\r
388 break;\r
389 }\r
390\r
391 //\r
392 // Get the handle\r
393 //\r
394 Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
395 Handle = (IHANDLE *) Prot->Handle;\r
396 *Interface = Prot->Interface;\r
397\r
398 //\r
399 // If this handle has not been returned this request, then \r
400 // return it now\r
401 //\r
402 if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
403 Handle->LocateRequest = mEfiLocateHandleRequest;\r
404 break;\r
405 }\r
406 }\r
407\r
408 return Handle;\r
409}\r
410\r
411\r
412\r
413EFI_STATUS\r
414EFIAPI\r
415CoreLocateDevicePath (\r
416 IN EFI_GUID *Protocol,\r
417 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,\r
418 OUT EFI_HANDLE *Device\r
419 )\r
420/*++\r
421\r
422Routine Description:\r
423\r
424 Locates the handle to a device on the device path that best matches the specified protocol.\r
425\r
426Arguments:\r
427\r
428 Protocol - The protocol to search for.\r
429 DevicePath - On input, a pointer to a pointer to the device path. On output, the device\r
430 path pointer is modified to point to the remaining part of the devicepath.\r
431 Device - A pointer to the returned device handle. \r
432\r
433Returns:\r
434\r
435 EFI_SUCCESS - The resulting handle was returned.\r
436 EFI_NOT_FOUND - No handles matched the search.\r
437 EFI_INVALID_PARAMETER - One of the parameters has an invalid value.\r
438\r
439--*/\r
440{\r
441 INTN SourceSize;\r
442 INTN Size;\r
443 INTN BestMatch;\r
444 UINTN HandleCount;\r
445 UINTN Index;\r
446 EFI_STATUS Status;\r
447 EFI_HANDLE *Handles;\r
448 EFI_HANDLE Handle;\r
449 EFI_DEVICE_PATH_PROTOCOL *SourcePath;\r
450 EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
451 \r
452 if (Protocol == NULL) {\r
453 return EFI_INVALID_PARAMETER;\r
454 }\r
455 \r
456 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
457 return EFI_INVALID_PARAMETER;\r
458 }\r
459 \r
460 if (Device == NULL) {\r
461 return EFI_INVALID_PARAMETER;\r
462 }\r
463 \r
464 *Device = NULL_HANDLE;\r
465 SourcePath = *DevicePath;\r
466 SourceSize = CoreDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
467 \r
468 //\r
469 // The source path can only have 1 instance\r
470 //\r
471 if (CoreIsDevicePathMultiInstance (SourcePath)) {\r
472 DEBUG((EFI_D_ERROR, "LocateDevicePath: Device path has too many instances\n"));\r
473 return EFI_INVALID_PARAMETER;\r
474 }\r
475\r
476 //\r
477 // Get a list of all handles that support the requested protocol\r
478 //\r
479 Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles);\r
480 if (EFI_ERROR (Status) || HandleCount == 0) {\r
481 return EFI_NOT_FOUND;\r
482 }\r
483\r
484 BestMatch = -1;\r
485 for(Index = 0; Index < HandleCount; Index += 1) {\r
486 Handle = Handles[Index];\r
487 Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath);\r
488 if (EFI_ERROR (Status)) {\r
489 //\r
490 // If this handle doesn't support device path, then skip it\r
491 //\r
492 continue;\r
493 }\r
494\r
495 //\r
496 // Check if DevicePath is first part of SourcePath\r
497 //\r
498 Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL);\r
499 if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) {\r
500 //\r
501 // If the size is equal to the best match, then we\r
502 // have a duplice device path for 2 different device\r
503 // handles\r
504 //\r
505 ASSERT (Size != BestMatch);\r
506 \r
507 //\r
508 // We've got a match, see if it's the best match so far\r
509 //\r
510 if (Size > BestMatch) {\r
511 BestMatch = Size;\r
512 *Device = Handle;\r
513 }\r
514 }\r
515 }\r
516\r
517 CoreFreePool (Handles);\r
518 \r
519 //\r
520 // If there wasn't any match, then no parts of the device path was found. \r
521 // Which is strange since there is likely a "root level" device path in the system.\r
522 //\r
523 if (BestMatch == -1) {\r
524 return EFI_NOT_FOUND;\r
525 }\r
526\r
527 //\r
528 // Return the remaining part of the device path\r
529 //\r
530 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch);\r
531 return EFI_SUCCESS;\r
532}\r
533\r
534\r
535 \r
536EFI_STATUS\r
537EFIAPI\r
538CoreLocateProtocol (\r
539 IN EFI_GUID *Protocol,\r
540 IN VOID *Registration OPTIONAL,\r
541 OUT VOID **Interface\r
542 )\r
543/*++\r
544\r
545Routine Description:\r
546\r
547 Return the first Protocol Interface that matches the Protocol GUID. If\r
548 Registration is pasased in return a Protocol Instance that was just add\r
549 to the system. If Retistration is NULL return the first Protocol Interface\r
550 you find.\r
551\r
552Arguments:\r
553\r
554 Protocol - The protocol to search for\r
555 \r
556 Registration - Optional Registration Key returned from RegisterProtocolNotify() \r
557\r
558 Interface - Return the Protocol interface (instance).\r
559\r
560Returns:\r
561\r
562 EFI_SUCCESS - If a valid Interface is returned\r
563 \r
564 EFI_INVALID_PARAMETER - Invalid parameter\r
565 \r
566 EFI_NOT_FOUND - Protocol interface not found\r
567\r
568--*/\r
569{\r
570 EFI_STATUS Status;\r
571 LOCATE_POSITION Position;\r
572 PROTOCOL_NOTIFY *ProtNotify;\r
573 IHANDLE *Handle;\r
574\r
575 if (Interface == NULL) {\r
576 return EFI_INVALID_PARAMETER;\r
577 }\r
578 \r
579 if (Protocol == NULL) {\r
580 return EFI_NOT_FOUND;\r
581 }\r
582 \r
583 *Interface = NULL;\r
584 Status = EFI_SUCCESS;\r
585\r
586 //\r
587 // Set initial position\r
588 //\r
589 Position.Protocol = Protocol;\r
590 Position.SearchKey = Registration;\r
591 Position.Position = &gHandleList;\r
592 \r
593 //\r
594 // Lock the protocol database\r
595 //\r
596 CoreAcquireProtocolLock ();\r
597\r
598 mEfiLocateHandleRequest += 1;\r
599\r
600 if (NULL == Registration) {\r
601 //\r
602 // Look up the protocol entry and set the head pointer\r
603 //\r
604 Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
605 if (Position.ProtEntry == NULL) {\r
606 Status = EFI_NOT_FOUND;\r
607 goto Done;\r
608 }\r
609 Position.Position = &Position.ProtEntry->Protocols;\r
610\r
611 Handle = CoreGetNextLocateByProtocol (&Position, Interface);\r
612 } else {\r
613 Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface); \r
614 }\r
615\r
616 if (NULL == Handle) {\r
617 Status = EFI_NOT_FOUND;\r
618 } else if (NULL != Registration) {\r
619 //\r
620 // If this is a search by register notify and a handle was\r
621 // returned, update the register notification position\r
622 // \r
623 ProtNotify = Registration;\r
624 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
625 }\r
626\r
627Done:\r
628 CoreReleaseProtocolLock ();\r
629 return Status;\r
630}\r
631\r
632\r
633 \r
634EFI_STATUS\r
635EFIAPI\r
636CoreLocateHandleBuffer (\r
637 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
638 IN EFI_GUID *Protocol OPTIONAL,\r
639 IN VOID *SearchKey OPTIONAL,\r
640 IN OUT UINTN *NumberHandles,\r
641 OUT EFI_HANDLE **Buffer\r
642 )\r
643/*++\r
644\r
645Routine Description:\r
646\r
647 Function returns an array of handles that support the requested protocol \r
648 in a buffer allocated from pool. This is a version of CoreLocateHandle()\r
649 that allocates a buffer for the caller.\r
650\r
651Arguments:\r
652\r
653 SearchType - Specifies which handle(s) are to be returned.\r
654 Protocol - Provides the protocol to search by. \r
655 This parameter is only valid for SearchType ByProtocol.\r
656 SearchKey - Supplies the search key depending on the SearchType.\r
657 NumberHandles - The number of handles returned in Buffer.\r
658 Buffer - A pointer to the buffer to return the requested array of \r
659 handles that support Protocol.\r
660\r
661Returns:\r
662 \r
663 EFI_SUCCESS - The result array of handles was returned.\r
664 EFI_NOT_FOUND - No handles match the search. \r
665 EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results.\r
666 EFI_INVALID_PARAMETER - Invalid parameter\r
667\r
668--*/\r
669{\r
670 EFI_STATUS Status;\r
671 UINTN BufferSize;\r
672\r
673 if (NumberHandles == NULL) {\r
674 return EFI_INVALID_PARAMETER;\r
675 }\r
676\r
677 if (Buffer == NULL) {\r
678 return EFI_INVALID_PARAMETER;\r
679 }\r
680\r
681 BufferSize = 0;\r
682 *NumberHandles = 0;\r
683 *Buffer = NULL;\r
684 Status = CoreLocateHandle (\r
685 SearchType,\r
686 Protocol,\r
687 SearchKey,\r
688 &BufferSize,\r
689 *Buffer\r
690 );\r
691 //\r
692 // LocateHandleBuffer() returns incorrect status code if SearchType is\r
693 // invalid.\r
694 //\r
695 // Add code to correctly handle expected errors from CoreLocateHandle().\r
696 //\r
697 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
698 if (Status != EFI_INVALID_PARAMETER) {\r
699 Status = EFI_NOT_FOUND;\r
700 }\r
701 return Status;\r
702 }\r
703\r
704 *Buffer = CoreAllocateBootServicesPool (BufferSize);\r
705 if (*Buffer == NULL) {\r
706 return EFI_OUT_OF_RESOURCES;\r
707 }\r
708\r
709 Status = CoreLocateHandle (\r
710 SearchType,\r
711 Protocol,\r
712 SearchKey,\r
713 &BufferSize,\r
714 *Buffer\r
715 );\r
716\r
717 *NumberHandles = BufferSize/sizeof(EFI_HANDLE);\r
718 if (EFI_ERROR(Status)) {\r
719 *NumberHandles = 0;\r
720 }\r
721\r
722 return Status;\r
723}\r
724\r
725\r