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