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