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