StandaloneMmPkg: Add CPU driver suitable for ARM Platforms.
[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
5 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>\r
6 This program and the accompanying materials are licensed and made available\r
7 under the terms and conditions of the BSD License which accompanies this\r
8 distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "StandaloneMmCore.h"\r
17\r
18//\r
19// ProtocolRequest - Last LocateHandle request ID\r
20//\r
21UINTN mEfiLocateHandleRequest = 0;\r
22\r
23//\r
24// Internal prototypes\r
25//\r
26\r
27typedef struct {\r
28 EFI_GUID *Protocol;\r
29 VOID *SearchKey;\r
30 LIST_ENTRY *Position;\r
31 PROTOCOL_ENTRY *ProtEntry;\r
32} LOCATE_POSITION;\r
33\r
34typedef\r
35IHANDLE *\r
36(* CORE_GET_NEXT) (\r
37 IN OUT LOCATE_POSITION *Position,\r
38 OUT VOID **Interface\r
39 );\r
40\r
41/**\r
42 Routine to get the next Handle, when you are searching for all handles.\r
43\r
44 @param Position Information about which Handle to seach for.\r
45 @param Interface Return the interface structure for the matching\r
46 protocol.\r
47\r
48 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
49 Otherwise,NULL is returned.\r
50\r
51**/\r
52IHANDLE *\r
53MmGetNextLocateAllHandles (\r
54 IN OUT LOCATE_POSITION *Position,\r
55 OUT VOID **Interface\r
56 )\r
57{\r
58 IHANDLE *Handle;\r
59\r
60 //\r
61 // Next handle\r
62 //\r
63 Position->Position = Position->Position->ForwardLink;\r
64\r
65 //\r
66 // If not at the end of the list, get the handle\r
67 //\r
68 Handle = NULL;\r
69 *Interface = NULL;\r
70 if (Position->Position != &gHandleList) {\r
71 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
72 }\r
73 return Handle;\r
74}\r
75\r
76/**\r
77 Routine to get the next Handle, when you are searching for register protocol\r
78 notifies.\r
79\r
80 @param Position Information about which Handle to seach for.\r
81 @param Interface Return the interface structure for the matching\r
82 protocol.\r
83\r
84 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
85 Otherwise,NULL is returned.\r
86\r
87**/\r
88IHANDLE *\r
89MmGetNextLocateByRegisterNotify (\r
90 IN OUT LOCATE_POSITION *Position,\r
91 OUT VOID **Interface\r
92 )\r
93{\r
94 IHANDLE *Handle;\r
95 PROTOCOL_NOTIFY *ProtNotify;\r
96 PROTOCOL_INTERFACE *Prot;\r
97 LIST_ENTRY *Link;\r
98\r
99 Handle = NULL;\r
100 *Interface = NULL;\r
101 ProtNotify = Position->SearchKey;\r
102\r
103 //\r
104 // If this is the first request, get the next handle\r
105 //\r
106 if (ProtNotify != NULL) {\r
107 ASSERT (ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);\r
108 Position->SearchKey = NULL;\r
109\r
110 //\r
111 // If not at the end of the list, get the next handle\r
112 //\r
113 Link = ProtNotify->Position->ForwardLink;\r
114 if (Link != &ProtNotify->Protocol->Protocols) {\r
115 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
116 Handle = Prot->Handle;\r
117 *Interface = Prot->Interface;\r
118 }\r
119 }\r
120 return Handle;\r
121}\r
122\r
123/**\r
124 Routine to get the next Handle, when you are searching for a given protocol.\r
125\r
126 @param Position Information about which Handle to seach for.\r
127 @param Interface Return the interface structure for the matching\r
128 protocol.\r
129\r
130 @return An pointer to IHANDLE if the next Position is not the end of the list.\r
131 Otherwise,NULL is returned.\r
132\r
133**/\r
134IHANDLE *\r
135MmGetNextLocateByProtocol (\r
136 IN OUT LOCATE_POSITION *Position,\r
137 OUT VOID **Interface\r
138 )\r
139{\r
140 IHANDLE *Handle;\r
141 LIST_ENTRY *Link;\r
142 PROTOCOL_INTERFACE *Prot;\r
143\r
144 Handle = NULL;\r
145 *Interface = NULL;\r
146 for (; ;) {\r
147 //\r
148 // Next entry\r
149 //\r
150 Link = Position->Position->ForwardLink;\r
151 Position->Position = Link;\r
152\r
153 //\r
154 // If not at the end, return the handle\r
155 //\r
156 if (Link == &Position->ProtEntry->Protocols) {\r
157 Handle = NULL;\r
158 break;\r
159 }\r
160\r
161 //\r
162 // Get the handle\r
163 //\r
164 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);\r
165 Handle = Prot->Handle;\r
166 *Interface = Prot->Interface;\r
167\r
168 //\r
169 // If this handle has not been returned this request, then\r
170 // return it now\r
171 //\r
172 if (Handle->LocateRequest != mEfiLocateHandleRequest) {\r
173 Handle->LocateRequest = mEfiLocateHandleRequest;\r
174 break;\r
175 }\r
176 }\r
177 return Handle;\r
178}\r
179\r
180/**\r
181 Return the first Protocol Interface that matches the Protocol GUID. If\r
182 Registration is pasased in return a Protocol Instance that was just add\r
183 to the system. If Retistration is NULL return the first Protocol Interface\r
184 you find.\r
185\r
186 @param Protocol The protocol to search for\r
187 @param Registration Optional Registration Key returned from\r
188 RegisterProtocolNotify()\r
189 @param Interface Return the Protocol interface (instance).\r
190\r
191 @retval EFI_SUCCESS If a valid Interface is returned\r
192 @retval EFI_INVALID_PARAMETER Invalid parameter\r
193 @retval EFI_NOT_FOUND Protocol interface not found\r
194\r
195**/\r
196EFI_STATUS\r
197EFIAPI\r
198MmLocateProtocol (\r
199 IN EFI_GUID *Protocol,\r
200 IN VOID *Registration OPTIONAL,\r
201 OUT VOID **Interface\r
202 )\r
203{\r
204 EFI_STATUS Status;\r
205 LOCATE_POSITION Position;\r
206 PROTOCOL_NOTIFY *ProtNotify;\r
207 IHANDLE *Handle;\r
208\r
209 if ((Interface == NULL) || (Protocol == NULL)) {\r
210 return EFI_INVALID_PARAMETER;\r
211 }\r
212\r
213 *Interface = NULL;\r
214 Status = EFI_SUCCESS;\r
215\r
216 //\r
217 // Set initial position\r
218 //\r
219 Position.Protocol = Protocol;\r
220 Position.SearchKey = Registration;\r
221 Position.Position = &gHandleList;\r
222\r
223 mEfiLocateHandleRequest += 1;\r
224\r
225 if (Registration == NULL) {\r
226 //\r
227 // Look up the protocol entry and set the head pointer\r
228 //\r
229 Position.ProtEntry = MmFindProtocolEntry (Protocol, FALSE);\r
230 if (Position.ProtEntry == NULL) {\r
231 return EFI_NOT_FOUND;\r
232 }\r
233 Position.Position = &Position.ProtEntry->Protocols;\r
234\r
235 Handle = MmGetNextLocateByProtocol (&Position, Interface);\r
236 } else {\r
237 Handle = MmGetNextLocateByRegisterNotify (&Position, Interface);\r
238 }\r
239\r
240 if (Handle == NULL) {\r
241 Status = EFI_NOT_FOUND;\r
242 } else if (Registration != NULL) {\r
243 //\r
244 // If this is a search by register notify and a handle was\r
245 // returned, update the register notification position\r
246 //\r
247 ProtNotify = Registration;\r
248 ProtNotify->Position = ProtNotify->Position->ForwardLink;\r
249 }\r
250\r
251 return Status;\r
252}\r
253\r
254/**\r
255 Locates the requested handle(s) and returns them in Buffer.\r
256\r
257 @param SearchType The type of search to perform to locate the\r
258 handles\r
259 @param Protocol The protocol to search for\r
260 @param SearchKey Dependant on SearchType\r
261 @param BufferSize On input the size of Buffer. On output the\r
262 size of data returned.\r
263 @param Buffer The buffer to return the results in\r
264\r
265 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is\r
266 returned in BufferSize.\r
267 @retval EFI_INVALID_PARAMETER Invalid parameter\r
268 @retval EFI_SUCCESS Successfully found the requested handle(s) and\r
269 returns them in Buffer.\r
270\r
271**/\r
272EFI_STATUS\r
273EFIAPI\r
274MmLocateHandle (\r
275 IN EFI_LOCATE_SEARCH_TYPE SearchType,\r
276 IN EFI_GUID *Protocol OPTIONAL,\r
277 IN VOID *SearchKey OPTIONAL,\r
278 IN OUT UINTN *BufferSize,\r
279 OUT EFI_HANDLE *Buffer\r
280 )\r
281{\r
282 EFI_STATUS Status;\r
283 LOCATE_POSITION Position;\r
284 PROTOCOL_NOTIFY *ProtNotify;\r
285 CORE_GET_NEXT GetNext;\r
286 UINTN ResultSize;\r
287 IHANDLE *Handle;\r
288 IHANDLE **ResultBuffer;\r
289 VOID *Interface;\r
290\r
291 if (BufferSize == NULL) {\r
292 return EFI_INVALID_PARAMETER;\r
293 }\r
294\r
295 if ((*BufferSize > 0) && (Buffer == NULL)) {\r
296 return EFI_INVALID_PARAMETER;\r
297 }\r
298\r
299 GetNext = NULL;\r
300\r
301 //\r
302 // Set initial position\r
303 //\r
304 Position.Protocol = Protocol;\r
305 Position.SearchKey = SearchKey;\r
306 Position.Position = &gHandleList;\r
307\r
308 ResultSize = 0;\r
309 ResultBuffer = (IHANDLE **) Buffer;\r
310 Status = EFI_SUCCESS;\r
311\r
312 //\r
313 // Get the search function based on type\r
314 //\r
315 switch (SearchType) {\r
316 case AllHandles:\r
317 GetNext = MmGetNextLocateAllHandles;\r
318 break;\r
319\r
320 case ByRegisterNotify:\r
321 GetNext = MmGetNextLocateByRegisterNotify;\r
322 //\r
323 // Must have SearchKey for locate ByRegisterNotify\r
324 //\r
325 if (SearchKey == NULL) {\r
326 Status = EFI_INVALID_PARAMETER;\r
327 }\r
328 break;\r
329\r
330 case ByProtocol:\r
331 GetNext = MmGetNextLocateByProtocol;\r
332 if (Protocol == NULL) {\r
333 Status = EFI_INVALID_PARAMETER;\r
334 break;\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 Position.Position = &Position.ProtEntry->Protocols;\r
345 break;\r
346\r
347 default:\r
348 Status = EFI_INVALID_PARAMETER;\r
349 break;\r
350 }\r
351\r
352 if (EFI_ERROR (Status)) {\r
353 return Status;\r
354 }\r
355\r
356 //\r
357 // Enumerate out the matching handles\r
358 //\r
359 mEfiLocateHandleRequest += 1;\r
360 for (; ;) {\r
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
373 ResultSize += sizeof (Handle);\r
374 if (ResultSize <= *BufferSize) {\r
375 *ResultBuffer = Handle;\r
376 ResultBuffer += 1;\r
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
397 if (SearchType == ByRegisterNotify && !EFI_ERROR (Status)) {\r
398 ASSERT (SearchKey != NULL);\r
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
403 ProtNotify = SearchKey;\r
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 MmLocateHandle()\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
430 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.\r
431\r
432**/\r
433EFI_STATUS\r
434EFIAPI\r
435MmLocateHandleBuffer (\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
454 BufferSize = 0;\r
455 *NumberHandles = 0;\r
456 *Buffer = NULL;\r
457 Status = MmLocateHandle (\r
458 SearchType,\r
459 Protocol,\r
460 SearchKey,\r
461 &BufferSize,\r
462 *Buffer\r
463 );\r
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 MmLocateHandle().\r
469 //\r
470 if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {\r
471 if (Status != EFI_INVALID_PARAMETER) {\r
472 Status = EFI_NOT_FOUND;\r
473 }\r
474 return Status;\r
475 }\r
476\r
477 *Buffer = AllocatePool (BufferSize);\r
478 if (*Buffer == NULL) {\r
479 return EFI_OUT_OF_RESOURCES;\r
480 }\r
481\r
482 Status = MmLocateHandle (\r
483 SearchType,\r
484 Protocol,\r
485 SearchKey,\r
486 &BufferSize,\r
487 *Buffer\r
488 );\r
489\r
490 *NumberHandles = BufferSize / sizeof(EFI_HANDLE);\r
491 if (EFI_ERROR (Status)) {\r
492 *NumberHandles = 0;\r
493 }\r
494\r
495 return Status;\r
496}\r