]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/Locate.c
Clean up DEC files:
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Locate.c
CommitLineData
e42e9404 1/** @file\r
2 Locate handle functions\r
3\r
cd5ebaa0 4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
e42e9404 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
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
208 if (Interface == NULL) {\r
209 return EFI_INVALID_PARAMETER;\r
210 }\r
211\r
212 if (Protocol == NULL) {\r
213 return EFI_NOT_FOUND;\r
214 }\r
215\r
216 *Interface = NULL;\r
217 Status = EFI_SUCCESS;\r
218\r
219 //\r
220 // Set initial position\r
221 //\r
222 Position.Protocol = Protocol;\r
223 Position.SearchKey = Registration;\r
224 Position.Position = &gHandleList;\r
225\r
226 mEfiLocateHandleRequest += 1;\r
227\r
228 if (Registration == NULL) {\r
229 //\r
230 // Look up the protocol entry and set the head pointer\r
231 //\r
232 Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);\r
233 if (Position.ProtEntry == NULL) {\r
234 return EFI_NOT_FOUND;\r
235 }\r
236 Position.Position = &Position.ProtEntry->Protocols;\r
237\r
238 Handle = SmmGetNextLocateByProtocol (&Position, Interface);\r
239 } else {\r
240 Handle = SmmGetNextLocateByRegisterNotify (&Position, Interface);\r
241 }\r
242\r
243 if (Handle == NULL) {\r
244 Status = EFI_NOT_FOUND;\r
245 } else if (Registration != NULL) {\r
246 //\r
247 // If this is a search by register notify and a handle was\r
248 // returned, update the register notification position\r
249 //\r
250 ProtNotify = Registration;\r
251 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
252 }\r
253\r
254 return Status;\r
255}\r
256\r
257/**\r
258 Locates the requested handle(s) and returns them in Buffer.\r
259\r
260 @param SearchType The type of search to perform to locate the\r
261 handles\r
262 @param Protocol The protocol to search for\r
263 @param SearchKey Dependant on SearchType\r
264 @param BufferSize On input the size of Buffer. On output the\r
265 size of data returned.\r
266 @param Buffer The buffer to return the results in\r
267\r
268 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is\r
269 returned in BufferSize.\r
270 @retval EFI_INVALID_PARAMETER Invalid parameter\r
271 @retval EFI_SUCCESS Successfully found the requested handle(s) and\r
272 returns them in Buffer.\r
273\r
274**/\r
275EFI_STATUS\r
276EFIAPI\r
277SmmLocateHandle (\r
278 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
279 IN EFI_GUID *Protocol OPTIONAL,\r
280 IN VOID *SearchKey OPTIONAL,\r
281 IN OUT UINTN *BufferSize,\r
282 OUT EFI_HANDLE *Buffer\r
283 )\r
284{\r
285 EFI_STATUS Status;\r
286 LOCATE_POSITION Position;\r
287 PROTOCOL_NOTIFY *ProtNotify;\r
288 CORE_GET_NEXT GetNext;\r
289 UINTN ResultSize;\r
290 IHANDLE *Handle;\r
291 IHANDLE **ResultBuffer;\r
292 VOID *Interface;\r
293\r
294 if (BufferSize == NULL) {\r
295 return EFI_INVALID_PARAMETER;\r
296 }\r
297\r
298 if ((*BufferSize > 0) && (Buffer == NULL)) {\r
299 return EFI_INVALID_PARAMETER;\r
300 }\r
301\r
302 GetNext = NULL;\r
303\r
304 //\r
305 // Set initial position\r
306 //\r
307 Position.Protocol = Protocol;\r
308 Position.SearchKey = SearchKey;\r
309 Position.Position = &gHandleList;\r
310\r
311 ResultSize = 0;\r
312 ResultBuffer = (IHANDLE **) Buffer;\r
313 Status = EFI_SUCCESS;\r
314\r
315 //\r
316 // Get the search function based on type\r
317 //\r
318 switch (SearchType) {\r
319 case AllHandles:\r
320 GetNext = SmmGetNextLocateAllHandles;\r
321 break;\r
322\r
323 case ByRegisterNotify:\r
5b422a7b 324 GetNext = SmmGetNextLocateByRegisterNotify;\r
e42e9404 325 //\r
326 // Must have SearchKey for locate ByRegisterNotify\r
327 //\r
328 if (SearchKey == NULL) {\r
329 Status = EFI_INVALID_PARAMETER;\r
e42e9404 330 }\r
e42e9404 331 break;\r
332\r
333 case ByProtocol:\r
334 GetNext = SmmGetNextLocateByProtocol;\r
335 if (Protocol == NULL) {\r
336 Status = EFI_INVALID_PARAMETER;\r
337 break;\r
338 }\r
339 //\r
340 // Look up the protocol entry and set the head pointer\r
341 //\r
342 Position.ProtEntry = SmmFindProtocolEntry (Protocol, FALSE);\r
343 if (Position.ProtEntry == NULL) {\r
344 Status = EFI_NOT_FOUND;\r
345 break;\r
346 }\r
347 Position.Position = &Position.ProtEntry->Protocols;\r
348 break;\r
349\r
350 default:\r
351 Status = EFI_INVALID_PARAMETER;\r
352 break;\r
353 }\r
354\r
355 if (EFI_ERROR(Status)) {\r
356 return Status;\r
357 }\r
358\r
359 //\r
360 // Enumerate out the matching handles\r
361 //\r
362 mEfiLocateHandleRequest += 1;\r
363 for (; ;) {\r
364 //\r
365 // Get the next handle. If no more handles, stop\r
366 //\r
367 Handle = GetNext (&Position, &Interface);\r
368 if (NULL == Handle) {\r
369 break;\r
370 }\r
371\r
372 //\r
373 // Increase the resulting buffer size, and if this handle\r
374 // fits return it\r
375 //\r
376 ResultSize += sizeof(Handle);\r
377 if (ResultSize <= *BufferSize) {\r
378 *ResultBuffer = Handle;\r
379 ResultBuffer += 1;\r
380 }\r
381 }\r
382\r
383 //\r
384 // If the result is a zero length buffer, then there were no\r
385 // matching handles\r
386 //\r
387 if (ResultSize == 0) {\r
388 Status = EFI_NOT_FOUND;\r
389 } else {\r
390 //\r
391 // Return the resulting buffer size. If it's larger than what\r
392 // was passed, then set the error code\r
393 //\r
394 if (ResultSize > *BufferSize) {\r
395 Status = EFI_BUFFER_TOO_SMALL;\r
396 }\r
397\r
398 *BufferSize = ResultSize;\r
399\r
400 if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) {\r
52c0d06b 401 ASSERT (SearchKey != NULL);\r
e42e9404 402 //\r
403 // If this is a search by register notify and a handle was\r
404 // returned, update the register notification position\r
405 //\r
406 ProtNotify = SearchKey;\r
407 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
408 }\r
409 }\r
410\r
411 return Status;\r
412}\r
413\r
414/**\r
415 Function returns an array of handles that support the requested protocol\r
416 in a buffer allocated from pool. This is a version of SmmLocateHandle()\r
417 that allocates a buffer for the caller.\r
418\r
419 @param SearchType Specifies which handle(s) are to be returned.\r
420 @param Protocol Provides the protocol to search by. This\r
421 parameter is only valid for SearchType\r
422 ByProtocol.\r
423 @param SearchKey Supplies the search key depending on the\r
424 SearchType.\r
425 @param NumberHandles The number of handles returned in Buffer.\r
426 @param Buffer A pointer to the buffer to return the requested\r
427 array of handles that support Protocol.\r
428\r
429 @retval EFI_SUCCESS The result array of handles was returned.\r
430 @retval EFI_NOT_FOUND No handles match the search.\r
431 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
432 matching results.\r
433 @retval EFI_INVALID_PARAMETER One or more paramters are not valid.\r
434\r
435**/\r
436EFI_STATUS\r
437EFIAPI\r
438SmmLocateHandleBuffer (\r
439 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
440 IN EFI_GUID *Protocol OPTIONAL,\r
441 IN VOID *SearchKey OPTIONAL,\r
442 IN OUT UINTN *NumberHandles,\r
443 OUT EFI_HANDLE **Buffer\r
444 )\r
445{\r
446 EFI_STATUS Status;\r
447 UINTN BufferSize;\r
448\r
449 if (NumberHandles == NULL) {\r
450 return EFI_INVALID_PARAMETER;\r
451 }\r
452\r
453 if (Buffer == NULL) {\r
454 return EFI_INVALID_PARAMETER;\r
455 }\r
456\r
457 BufferSize = 0;\r
458 *NumberHandles = 0;\r
459 *Buffer = NULL;\r
460 Status = SmmLocateHandle (\r
461 SearchType,\r
462 Protocol,\r
463 SearchKey,\r
464 &BufferSize,\r
465 *Buffer\r
466 );\r
467 //\r
468 // LocateHandleBuffer() returns incorrect status code if SearchType is\r
469 // invalid.\r
470 //\r
471 // Add code to correctly handle expected errors from SmmLocateHandle().\r
472 //\r
473 if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
474 if (Status != EFI_INVALID_PARAMETER) {\r
475 Status = EFI_NOT_FOUND;\r
476 }\r
477 return Status;\r
478 }\r
479\r
480 *Buffer = AllocatePool (BufferSize);\r
481 if (*Buffer == NULL) {\r
482 return EFI_OUT_OF_RESOURCES;\r
483 }\r
484\r
485 Status = SmmLocateHandle (\r
486 SearchType,\r
487 Protocol,\r
488 SearchKey,\r
489 &BufferSize,\r
490 *Buffer\r
491 );\r
492\r
493 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
494 if (EFI_ERROR(Status)) {\r
495 *NumberHandles = 0;\r
496 }\r
497\r
498 return Status;\r
499}\r