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