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