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