]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Core/Locate.c
StandaloneMmPkg: Apply uncrustify changes
[mirror_edk2.git] / StandaloneMmPkg / Core / Locate.c
1 /** @file
2 Locate handle functions
3
4 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "StandaloneMmCore.h"
11
12 //
13 // ProtocolRequest - Last LocateHandle request ID
14 //
15 UINTN mEfiLocateHandleRequest = 0;
16
17 //
18 // Internal prototypes
19 //
20
21 typedef struct {
22 EFI_GUID *Protocol;
23 VOID *SearchKey;
24 LIST_ENTRY *Position;
25 PROTOCOL_ENTRY *ProtEntry;
26 } LOCATE_POSITION;
27
28 typedef
29 IHANDLE *
30 (*CORE_GET_NEXT) (
31 IN OUT LOCATE_POSITION *Position,
32 OUT VOID **Interface
33 );
34
35 /**
36 Routine to get the next Handle, when you are searching for all handles.
37
38 @param Position Information about which Handle to seach for.
39 @param Interface Return the interface structure for the matching
40 protocol.
41
42 @return An pointer to IHANDLE if the next Position is not the end of the list.
43 Otherwise,NULL is returned.
44
45 **/
46 IHANDLE *
47 MmGetNextLocateAllHandles (
48 IN OUT LOCATE_POSITION *Position,
49 OUT VOID **Interface
50 )
51 {
52 IHANDLE *Handle;
53
54 //
55 // Next handle
56 //
57 Position->Position = Position->Position->ForwardLink;
58
59 //
60 // If not at the end of the list, get the handle
61 //
62 Handle = NULL;
63 *Interface = NULL;
64 if (Position->Position != &gHandleList) {
65 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
66 }
67
68 return Handle;
69 }
70
71 /**
72 Routine to get the next Handle, when you are searching for register protocol
73 notifies.
74
75 @param Position Information about which Handle to seach for.
76 @param Interface Return the interface structure for the matching
77 protocol.
78
79 @return An pointer to IHANDLE if the next Position is not the end of the list.
80 Otherwise,NULL is returned.
81
82 **/
83 IHANDLE *
84 MmGetNextLocateByRegisterNotify (
85 IN OUT LOCATE_POSITION *Position,
86 OUT VOID **Interface
87 )
88 {
89 IHANDLE *Handle;
90 PROTOCOL_NOTIFY *ProtNotify;
91 PROTOCOL_INTERFACE *Prot;
92 LIST_ENTRY *Link;
93
94 Handle = NULL;
95 *Interface = NULL;
96 ProtNotify = Position->SearchKey;
97
98 //
99 // If this is the first request, get the next handle
100 //
101 if (ProtNotify != NULL) {
102 ASSERT (ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
103 Position->SearchKey = NULL;
104
105 //
106 // If not at the end of the list, get the next handle
107 //
108 Link = ProtNotify->Position->ForwardLink;
109 if (Link != &ProtNotify->Protocol->Protocols) {
110 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
111 Handle = Prot->Handle;
112 *Interface = Prot->Interface;
113 }
114 }
115
116 return Handle;
117 }
118
119 /**
120 Routine to get the next Handle, when you are searching for a given protocol.
121
122 @param Position Information about which Handle to seach for.
123 @param Interface Return the interface structure for the matching
124 protocol.
125
126 @return An pointer to IHANDLE if the next Position is not the end of the list.
127 Otherwise,NULL is returned.
128
129 **/
130 IHANDLE *
131 MmGetNextLocateByProtocol (
132 IN OUT LOCATE_POSITION *Position,
133 OUT VOID **Interface
134 )
135 {
136 IHANDLE *Handle;
137 LIST_ENTRY *Link;
138 PROTOCOL_INTERFACE *Prot;
139
140 Handle = NULL;
141 *Interface = NULL;
142 for ( ; ;) {
143 //
144 // Next entry
145 //
146 Link = Position->Position->ForwardLink;
147 Position->Position = Link;
148
149 //
150 // If not at the end, return the handle
151 //
152 if (Link == &Position->ProtEntry->Protocols) {
153 Handle = NULL;
154 break;
155 }
156
157 //
158 // Get the handle
159 //
160 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
161 Handle = Prot->Handle;
162 *Interface = Prot->Interface;
163
164 //
165 // If this handle has not been returned this request, then
166 // return it now
167 //
168 if (Handle->LocateRequest != mEfiLocateHandleRequest) {
169 Handle->LocateRequest = mEfiLocateHandleRequest;
170 break;
171 }
172 }
173
174 return Handle;
175 }
176
177 /**
178 Return the first Protocol Interface that matches the Protocol GUID. If
179 Registration is passed in return a Protocol Instance that was just add
180 to the system. If Registration is NULL return the first Protocol Interface
181 you find.
182
183 @param Protocol The protocol to search for
184 @param Registration Optional Registration Key returned from
185 RegisterProtocolNotify()
186 @param Interface Return the Protocol interface (instance).
187
188 @retval EFI_SUCCESS If a valid Interface is returned
189 @retval EFI_INVALID_PARAMETER Invalid parameter
190 @retval EFI_NOT_FOUND Protocol interface not found
191
192 **/
193 EFI_STATUS
194 EFIAPI
195 MmLocateProtocol (
196 IN EFI_GUID *Protocol,
197 IN VOID *Registration OPTIONAL,
198 OUT VOID **Interface
199 )
200 {
201 EFI_STATUS Status;
202 LOCATE_POSITION Position;
203 PROTOCOL_NOTIFY *ProtNotify;
204 IHANDLE *Handle;
205
206 if ((Interface == NULL) || (Protocol == NULL)) {
207 return EFI_INVALID_PARAMETER;
208 }
209
210 *Interface = NULL;
211 Status = EFI_SUCCESS;
212
213 //
214 // Set initial position
215 //
216 Position.Protocol = Protocol;
217 Position.SearchKey = Registration;
218 Position.Position = &gHandleList;
219
220 mEfiLocateHandleRequest += 1;
221
222 if (Registration == NULL) {
223 //
224 // Look up the protocol entry and set the head pointer
225 //
226 Position.ProtEntry = MmFindProtocolEntry (Protocol, FALSE);
227 if (Position.ProtEntry == NULL) {
228 return EFI_NOT_FOUND;
229 }
230
231 Position.Position = &Position.ProtEntry->Protocols;
232
233 Handle = MmGetNextLocateByProtocol (&Position, Interface);
234 } else {
235 Handle = MmGetNextLocateByRegisterNotify (&Position, Interface);
236 }
237
238 if (Handle == NULL) {
239 Status = EFI_NOT_FOUND;
240 } else if (Registration != NULL) {
241 //
242 // If this is a search by register notify and a handle was
243 // returned, update the register notification position
244 //
245 ProtNotify = Registration;
246 ProtNotify->Position = ProtNotify->Position->ForwardLink;
247 }
248
249 return Status;
250 }
251
252 /**
253 Locates the requested handle(s) and returns them in Buffer.
254
255 @param SearchType The type of search to perform to locate the
256 handles
257 @param Protocol The protocol to search for
258 @param SearchKey Dependant on SearchType
259 @param BufferSize On input the size of Buffer. On output the
260 size of data returned.
261 @param Buffer The buffer to return the results in
262
263 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
264 returned in BufferSize.
265 @retval EFI_INVALID_PARAMETER Invalid parameter
266 @retval EFI_SUCCESS Successfully found the requested handle(s) and
267 returns them in Buffer.
268
269 **/
270 EFI_STATUS
271 EFIAPI
272 MmLocateHandle (
273 IN EFI_LOCATE_SEARCH_TYPE SearchType,
274 IN EFI_GUID *Protocol OPTIONAL,
275 IN VOID *SearchKey OPTIONAL,
276 IN OUT UINTN *BufferSize,
277 OUT EFI_HANDLE *Buffer
278 )
279 {
280 EFI_STATUS Status;
281 LOCATE_POSITION Position;
282 PROTOCOL_NOTIFY *ProtNotify;
283 CORE_GET_NEXT GetNext;
284 UINTN ResultSize;
285 IHANDLE *Handle;
286 IHANDLE **ResultBuffer;
287 VOID *Interface;
288
289 if (BufferSize == NULL) {
290 return EFI_INVALID_PARAMETER;
291 }
292
293 if ((*BufferSize > 0) && (Buffer == NULL)) {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 GetNext = NULL;
298
299 //
300 // Set initial position
301 //
302 Position.Protocol = Protocol;
303 Position.SearchKey = SearchKey;
304 Position.Position = &gHandleList;
305
306 ResultSize = 0;
307 ResultBuffer = (IHANDLE **)Buffer;
308 Status = EFI_SUCCESS;
309
310 //
311 // Get the search function based on type
312 //
313 switch (SearchType) {
314 case AllHandles:
315 GetNext = MmGetNextLocateAllHandles;
316 break;
317
318 case ByRegisterNotify:
319 GetNext = MmGetNextLocateByRegisterNotify;
320 //
321 // Must have SearchKey for locate ByRegisterNotify
322 //
323 if (SearchKey == NULL) {
324 Status = EFI_INVALID_PARAMETER;
325 }
326
327 break;
328
329 case ByProtocol:
330 GetNext = MmGetNextLocateByProtocol;
331 if (Protocol == NULL) {
332 Status = EFI_INVALID_PARAMETER;
333 break;
334 }
335
336 //
337 // Look up the protocol entry and set the head pointer
338 //
339 Position.ProtEntry = MmFindProtocolEntry (Protocol, FALSE);
340 if (Position.ProtEntry == NULL) {
341 Status = EFI_NOT_FOUND;
342 break;
343 }
344
345 Position.Position = &Position.ProtEntry->Protocols;
346 break;
347
348 default:
349 Status = EFI_INVALID_PARAMETER;
350 break;
351 }
352
353 if (EFI_ERROR (Status)) {
354 return Status;
355 }
356
357 //
358 // Enumerate out the matching handles
359 //
360 mEfiLocateHandleRequest += 1;
361 for ( ; ;) {
362 //
363 // Get the next handle. If no more handles, stop
364 //
365 Handle = GetNext (&Position, &Interface);
366 if (NULL == Handle) {
367 break;
368 }
369
370 //
371 // Increase the resulting buffer size, and if this handle
372 // fits return it
373 //
374 ResultSize += sizeof (Handle);
375 if (ResultSize <= *BufferSize) {
376 *ResultBuffer = Handle;
377 ResultBuffer += 1;
378 }
379 }
380
381 //
382 // If the result is a zero length buffer, then there were no
383 // matching handles
384 //
385 if (ResultSize == 0) {
386 Status = EFI_NOT_FOUND;
387 } else {
388 //
389 // Return the resulting buffer size. If it's larger than what
390 // was passed, then set the error code
391 //
392 if (ResultSize > *BufferSize) {
393 Status = EFI_BUFFER_TOO_SMALL;
394 }
395
396 *BufferSize = ResultSize;
397
398 if ((SearchType == ByRegisterNotify) && !EFI_ERROR (Status)) {
399 ASSERT (SearchKey != NULL);
400 //
401 // If this is a search by register notify and a handle was
402 // returned, update the register notification position
403 //
404 ProtNotify = SearchKey;
405 ProtNotify->Position = ProtNotify->Position->ForwardLink;
406 }
407 }
408
409 return Status;
410 }
411
412 /**
413 Function returns an array of handles that support the requested protocol
414 in a buffer allocated from pool. This is a version of MmLocateHandle()
415 that allocates a buffer for the caller.
416
417 @param SearchType Specifies which handle(s) are to be returned.
418 @param Protocol Provides the protocol to search by. This
419 parameter is only valid for SearchType
420 ByProtocol.
421 @param SearchKey Supplies the search key depending on the
422 SearchType.
423 @param NumberHandles The number of handles returned in Buffer.
424 @param Buffer A pointer to the buffer to return the requested
425 array of handles that support Protocol.
426
427 @retval EFI_SUCCESS The result array of handles was returned.
428 @retval EFI_NOT_FOUND No handles match the search.
429 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
430 matching results.
431 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
432
433 **/
434 EFI_STATUS
435 EFIAPI
436 MmLocateHandleBuffer (
437 IN EFI_LOCATE_SEARCH_TYPE SearchType,
438 IN EFI_GUID *Protocol OPTIONAL,
439 IN VOID *SearchKey OPTIONAL,
440 IN OUT UINTN *NumberHandles,
441 OUT EFI_HANDLE **Buffer
442 )
443 {
444 EFI_STATUS Status;
445 UINTN BufferSize;
446
447 if (NumberHandles == NULL) {
448 return EFI_INVALID_PARAMETER;
449 }
450
451 if (Buffer == NULL) {
452 return EFI_INVALID_PARAMETER;
453 }
454
455 BufferSize = 0;
456 *NumberHandles = 0;
457 *Buffer = NULL;
458 Status = MmLocateHandle (
459 SearchType,
460 Protocol,
461 SearchKey,
462 &BufferSize,
463 *Buffer
464 );
465 //
466 // LocateHandleBuffer() returns incorrect status code if SearchType is
467 // invalid.
468 //
469 // Add code to correctly handle expected errors from MmLocateHandle().
470 //
471 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
472 if (Status != EFI_INVALID_PARAMETER) {
473 Status = EFI_NOT_FOUND;
474 }
475
476 return Status;
477 }
478
479 *Buffer = AllocatePool (BufferSize);
480 if (*Buffer == NULL) {
481 return EFI_OUT_OF_RESOURCES;
482 }
483
484 Status = MmLocateHandle (
485 SearchType,
486 Protocol,
487 SearchKey,
488 &BufferSize,
489 *Buffer
490 );
491
492 *NumberHandles = BufferSize / sizeof (EFI_HANDLE);
493 if (EFI_ERROR (Status)) {
494 *NumberHandles = 0;
495 }
496
497 return Status;
498 }