]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/PiSmmCore/Locate.c
MdeModulePkg: Return invalid param in LocateProtocol for Protocol==NULL
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / Locate.c
CommitLineData
e42e9404 1/** @file\r
2 Locate handle functions\r
3\r
415fc5e5 4 Copyright (c) 2009 - 2017, 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
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