]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Hand/Handle.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Hand / Handle.c
CommitLineData
23c98c94 1/** @file\r
162ed594 2 UEFI handle & protocol handling.\r
28a00297 3\r
d1102dba 4Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
28a00297 6\r
504214c4 7**/\r
28a00297 8\r
9c4ac31c 9#include "DxeMain.h"\r
ec90508b 10#include "Handle.h"\r
28a00297 11\r
28a00297 12//\r
13// mProtocolDatabase - A list of all protocols in the system. (simple list for now)\r
14// gHandleList - A list of all the handles in the system\r
15// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase\r
16// gHandleDatabaseKey - The Key to show that the handle has been created/modified\r
17//\r
1436aea4
MK
18LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);\r
19LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);\r
20EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
21UINT64 gHandleDatabaseKey = 0;\r
162ed594 22\r
23/**\r
24 Acquire lock on gProtocolDatabaseLock.\r
25\r
26**/\r
28a00297 27VOID\r
28CoreAcquireProtocolLock (\r
29 VOID\r
30 )\r
28a00297 31{\r
32 CoreAcquireLock (&gProtocolDatabaseLock);\r
33}\r
34\r
162ed594 35/**\r
36 Release lock on gProtocolDatabaseLock.\r
37\r
38**/\r
28a00297 39VOID\r
40CoreReleaseProtocolLock (\r
41 VOID\r
42 )\r
28a00297 43{\r
44 CoreReleaseLock (&gProtocolDatabaseLock);\r
45}\r
46\r
162ed594 47/**\r
28a00297 48 Check whether a handle is a valid EFI_HANDLE\r
a7fcab7a 49 The gProtocolDatabaseLock must be owned\r
28a00297 50\r
022c6d45 51 @param UserHandle The handle to check\r
28a00297 52\r
022c6d45 53 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.\r
162ed594 54 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.\r
28a00297 55\r
162ed594 56**/\r
57EFI_STATUS\r
58CoreValidateHandle (\r
1436aea4 59 IN EFI_HANDLE UserHandle\r
162ed594 60 )\r
28a00297 61{\r
1436aea4
MK
62 IHANDLE *Handle;\r
63 LIST_ENTRY *Link;\r
28a00297 64\r
5fc3889b 65 if (UserHandle == NULL) {\r
28a00297 66 return EFI_INVALID_PARAMETER;\r
67 }\r
5fc3889b 68\r
1436aea4 69 ASSERT_LOCKED (&gProtocolDatabaseLock);\r
a7fcab7a 70\r
5fc3889b
RN
71 for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {\r
72 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1436aea4 73 if (Handle == (IHANDLE *)UserHandle) {\r
5fc3889b
RN
74 return EFI_SUCCESS;\r
75 }\r
28a00297 76 }\r
5fc3889b
RN
77\r
78 return EFI_INVALID_PARAMETER;\r
28a00297 79}\r
80\r
162ed594 81/**\r
28a00297 82 Finds the protocol entry for the requested protocol.\r
28a00297 83 The gProtocolDatabaseLock must be owned\r
84\r
022c6d45 85 @param Protocol The ID of the protocol\r
86 @param Create Create a new entry if not found\r
28a00297 87\r
162ed594 88 @return Protocol entry\r
28a00297 89\r
162ed594 90**/\r
91PROTOCOL_ENTRY *\r
92CoreFindProtocolEntry (\r
1436aea4
MK
93 IN EFI_GUID *Protocol,\r
94 IN BOOLEAN Create\r
162ed594 95 )\r
28a00297 96{\r
1436aea4
MK
97 LIST_ENTRY *Link;\r
98 PROTOCOL_ENTRY *Item;\r
99 PROTOCOL_ENTRY *ProtEntry;\r
28a00297 100\r
1436aea4 101 ASSERT_LOCKED (&gProtocolDatabaseLock);\r
28a00297 102\r
103 //\r
104 // Search the database for the matching GUID\r
105 //\r
106\r
107 ProtEntry = NULL;\r
022c6d45 108 for (Link = mProtocolDatabase.ForwardLink;\r
109 Link != &mProtocolDatabase;\r
1436aea4
MK
110 Link = Link->ForwardLink)\r
111 {\r
112 Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
28a00297 113 if (CompareGuid (&Item->ProtocolID, Protocol)) {\r
28a00297 114 //\r
115 // This is the protocol entry\r
116 //\r
117\r
118 ProtEntry = Item;\r
119 break;\r
120 }\r
121 }\r
122\r
123 //\r
022c6d45 124 // If the protocol entry was not found and Create is TRUE, then\r
28a00297 125 // allocate a new entry\r
022c6d45 126 //\r
28a00297 127 if ((ProtEntry == NULL) && Create) {\r
1436aea4 128 ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));\r
022c6d45 129\r
28a00297 130 if (ProtEntry != NULL) {\r
131 //\r
132 // Initialize new protocol entry structure\r
133 //\r
134 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;\r
e94a9ff7 135 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);\r
28a00297 136 InitializeListHead (&ProtEntry->Protocols);\r
137 InitializeListHead (&ProtEntry->Notify);\r
138\r
139 //\r
140 // Add it to protocol database\r
141 //\r
142 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);\r
143 }\r
144 }\r
145\r
146 return ProtEntry;\r
147}\r
148\r
162ed594 149/**\r
150 Finds the protocol instance for the requested handle and protocol.\r
151 Note: This function doesn't do parameters checking, it's caller's responsibility\r
152 to pass in valid parameters.\r
153\r
022c6d45 154 @param Handle The handle to search the protocol on\r
155 @param Protocol GUID of the protocol\r
156 @param Interface The interface for the protocol being searched\r
162ed594 157\r
158 @return Protocol instance (NULL: Not found)\r
159\r
160**/\r
28a00297 161PROTOCOL_INTERFACE *\r
162CoreFindProtocolInterface (\r
1436aea4
MK
163 IN IHANDLE *Handle,\r
164 IN EFI_GUID *Protocol,\r
165 IN VOID *Interface\r
28a00297 166 )\r
28a00297 167{\r
168 PROTOCOL_INTERFACE *Prot;\r
169 PROTOCOL_ENTRY *ProtEntry;\r
170 LIST_ENTRY *Link;\r
171\r
1436aea4 172 ASSERT_LOCKED (&gProtocolDatabaseLock);\r
28a00297 173 Prot = NULL;\r
174\r
175 //\r
176 // Lookup the protocol entry for this protocol ID\r
177 //\r
178\r
179 ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);\r
180 if (ProtEntry != NULL) {\r
28a00297 181 //\r
182 // Look at each protocol interface for any matches\r
183 //\r
1436aea4 184 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
28a00297 185 //\r
186 // If this protocol interface matches, remove it\r
187 //\r
1436aea4
MK
188 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
189 if ((Prot->Interface == Interface) && (Prot->Protocol == ProtEntry)) {\r
28a00297 190 break;\r
191 }\r
192\r
193 Prot = NULL;\r
194 }\r
195 }\r
196\r
197 return Prot;\r
198}\r
199\r
162ed594 200/**\r
28a00297 201 Removes an event from a register protocol notify list on a protocol.\r
202\r
022c6d45 203 @param Event The event to search for in the protocol\r
204 database.\r
28a00297 205\r
162ed594 206 @return EFI_SUCCESS if the event was found and removed.\r
207 @return EFI_NOT_FOUND if the event was not found in the protocl database.\r
28a00297 208\r
162ed594 209**/\r
162ed594 210EFI_STATUS\r
211CoreUnregisterProtocolNotifyEvent (\r
1436aea4 212 IN EFI_EVENT Event\r
162ed594 213 )\r
28a00297 214{\r
1436aea4
MK
215 LIST_ENTRY *Link;\r
216 PROTOCOL_ENTRY *ProtEntry;\r
217 LIST_ENTRY *NotifyLink;\r
218 PROTOCOL_NOTIFY *ProtNotify;\r
28a00297 219\r
220 CoreAcquireProtocolLock ();\r
221\r
022c6d45 222 for ( Link = mProtocolDatabase.ForwardLink;\r
223 Link != &mProtocolDatabase;\r
1436aea4
MK
224 Link = Link->ForwardLink)\r
225 {\r
226 ProtEntry = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);\r
28a00297 227\r
022c6d45 228 for ( NotifyLink = ProtEntry->Notify.ForwardLink;\r
229 NotifyLink != &ProtEntry->Notify;\r
1436aea4
MK
230 NotifyLink = NotifyLink->ForwardLink)\r
231 {\r
232 ProtNotify = CR (NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);\r
28a00297 233\r
234 if (ProtNotify->Event == Event) {\r
1436aea4
MK
235 RemoveEntryList (&ProtNotify->Link);\r
236 CoreFreePool (ProtNotify);\r
28a00297 237 CoreReleaseProtocolLock ();\r
238 return EFI_SUCCESS;\r
239 }\r
240 }\r
241 }\r
242\r
243 CoreReleaseProtocolLock ();\r
244 return EFI_NOT_FOUND;\r
245}\r
246\r
162ed594 247/**\r
28a00297 248 Removes all the events in the protocol database that match Event.\r
249\r
022c6d45 250 @param Event The event to search for in the protocol\r
251 database.\r
28a00297 252\r
162ed594 253 @return EFI_SUCCESS when done searching the entire database.\r
28a00297 254\r
162ed594 255**/\r
256EFI_STATUS\r
257CoreUnregisterProtocolNotify (\r
1436aea4 258 IN EFI_EVENT Event\r
162ed594 259 )\r
28a00297 260{\r
1436aea4 261 EFI_STATUS Status;\r
28a00297 262\r
263 do {\r
264 Status = CoreUnregisterProtocolNotifyEvent (Event);\r
265 } while (!EFI_ERROR (Status));\r
266\r
267 return EFI_SUCCESS;\r
268}\r
269\r
162ed594 270/**\r
271 Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which\r
272 Calls the private one which contains a BOOLEAN parameter for notifications\r
273\r
022c6d45 274 @param UserHandle The handle to install the protocol handler on,\r
275 or NULL if a new handle is to be allocated\r
276 @param Protocol The protocol to add to the handle\r
277 @param InterfaceType Indicates whether Interface is supplied in\r
278 native form.\r
279 @param Interface The interface for the protocol being added\r
162ed594 280\r
281 @return Status code\r
282\r
283**/\r
28a00297 284EFI_STATUS\r
285EFIAPI\r
286CoreInstallProtocolInterface (\r
1436aea4
MK
287 IN OUT EFI_HANDLE *UserHandle,\r
288 IN EFI_GUID *Protocol,\r
289 IN EFI_INTERFACE_TYPE InterfaceType,\r
290 IN VOID *Interface\r
28a00297 291 )\r
28a00297 292{\r
293 return CoreInstallProtocolInterfaceNotify (\r
1436aea4
MK
294 UserHandle,\r
295 Protocol,\r
296 InterfaceType,\r
297 Interface,\r
298 TRUE\r
299 );\r
28a00297 300}\r
301\r
162ed594 302/**\r
303 Installs a protocol interface into the boot services environment.\r
304\r
022c6d45 305 @param UserHandle The handle to install the protocol handler on,\r
306 or NULL if a new handle is to be allocated\r
307 @param Protocol The protocol to add to the handle\r
308 @param InterfaceType Indicates whether Interface is supplied in\r
309 native form.\r
310 @param Interface The interface for the protocol being added\r
311 @param Notify indicates whether notify the notification list\r
312 for this protocol\r
313\r
314 @retval EFI_INVALID_PARAMETER Invalid parameter\r
315 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate\r
162ed594 316 @retval EFI_SUCCESS Protocol interface successfully installed\r
317\r
318**/\r
28a00297 319EFI_STATUS\r
320CoreInstallProtocolInterfaceNotify (\r
1436aea4
MK
321 IN OUT EFI_HANDLE *UserHandle,\r
322 IN EFI_GUID *Protocol,\r
323 IN EFI_INTERFACE_TYPE InterfaceType,\r
324 IN VOID *Interface,\r
325 IN BOOLEAN Notify\r
28a00297 326 )\r
28a00297 327{\r
328 PROTOCOL_INTERFACE *Prot;\r
329 PROTOCOL_ENTRY *ProtEntry;\r
330 IHANDLE *Handle;\r
331 EFI_STATUS Status;\r
332 VOID *ExistingInterface;\r
333\r
334 //\r
335 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.\r
336 // Also added check for invalid UserHandle and Protocol pointers.\r
337 //\r
1436aea4 338 if ((UserHandle == NULL) || (Protocol == NULL)) {\r
28a00297 339 return EFI_INVALID_PARAMETER;\r
340 }\r
341\r
342 if (InterfaceType != EFI_NATIVE_INTERFACE) {\r
343 return EFI_INVALID_PARAMETER;\r
344 }\r
345\r
346 //\r
347 // Print debug message\r
348 //\r
1436aea4 349 DEBUG ((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));\r
28a00297 350\r
351 Status = EFI_OUT_OF_RESOURCES;\r
1436aea4 352 Prot = NULL;\r
28a00297 353 Handle = NULL;\r
354\r
4008328a 355 if (*UserHandle != NULL) {\r
28a00297 356 Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);\r
357 if (!EFI_ERROR (Status)) {\r
358 return EFI_INVALID_PARAMETER;\r
359 }\r
360 }\r
361\r
362 //\r
022c6d45 363 // Lock the protocol database\r
28a00297 364 //\r
365 CoreAcquireProtocolLock ();\r
366\r
367 //\r
368 // Lookup the Protocol Entry for the requested protocol\r
369 //\r
370 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);\r
371 if (ProtEntry == NULL) {\r
372 goto Done;\r
373 }\r
374\r
375 //\r
376 // Allocate a new protocol interface structure\r
377 //\r
1436aea4 378 Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));\r
28a00297 379 if (Prot == NULL) {\r
380 Status = EFI_OUT_OF_RESOURCES;\r
381 goto Done;\r
382 }\r
383\r
384 //\r
385 // If caller didn't supply a handle, allocate a new one\r
386 //\r
387 Handle = (IHANDLE *)*UserHandle;\r
388 if (Handle == NULL) {\r
1436aea4 389 Handle = AllocateZeroPool (sizeof (IHANDLE));\r
28a00297 390 if (Handle == NULL) {\r
391 Status = EFI_OUT_OF_RESOURCES;\r
392 goto Done;\r
393 }\r
394\r
395 //\r
396 // Initialize new handler structure\r
397 //\r
398 Handle->Signature = EFI_HANDLE_SIGNATURE;\r
399 InitializeListHead (&Handle->Protocols);\r
400\r
401 //\r
402 // Initialize the Key to show that the handle has been created/modified\r
403 //\r
404 gHandleDatabaseKey++;\r
405 Handle->Key = gHandleDatabaseKey;\r
406\r
407 //\r
408 // Add this handle to the list global list of all handles\r
409 // in the system\r
410 //\r
411 InsertTailList (&gHandleList, &Handle->AllHandles);\r
c01f13d5
SZ
412 } else {\r
413 Status = CoreValidateHandle (Handle);\r
414 if (EFI_ERROR (Status)) {\r
1436aea4 415 DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));\r
c01f13d5
SZ
416 goto Done;\r
417 }\r
28a00297 418 }\r
419\r
420 //\r
421 // Each interface that is added must be unique\r
422 //\r
423 ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);\r
424\r
425 //\r
426 // Initialize the protocol interface structure\r
427 //\r
428 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;\r
1436aea4
MK
429 Prot->Handle = Handle;\r
430 Prot->Protocol = ProtEntry;\r
28a00297 431 Prot->Interface = Interface;\r
432\r
433 //\r
434 // Initalize OpenProtocol Data base\r
435 //\r
436 InitializeListHead (&Prot->OpenList);\r
437 Prot->OpenListCount = 0;\r
438\r
439 //\r
022c6d45 440 // Add this protocol interface to the head of the supported\r
28a00297 441 // protocol list for this handle\r
442 //\r
443 InsertHeadList (&Handle->Protocols, &Prot->Link);\r
444\r
445 //\r
022c6d45 446 // Add this protocol interface to the tail of the\r
28a00297 447 // protocol entry\r
022c6d45 448 //\r
28a00297 449 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);\r
450\r
451 //\r
022c6d45 452 // Notify the notification list for this protocol\r
28a00297 453 //\r
454 if (Notify) {\r
455 CoreNotifyProtocolEntry (ProtEntry);\r
456 }\r
1436aea4 457\r
28a00297 458 Status = EFI_SUCCESS;\r
459\r
460Done:\r
461 //\r
462 // Done, unlock the database and return\r
463 //\r
464 CoreReleaseProtocolLock ();\r
465 if (!EFI_ERROR (Status)) {\r
466 //\r
467 // Return the new handle back to the caller\r
468 //\r
469 *UserHandle = Handle;\r
470 } else {\r
471 //\r
472 // There was an error, clean up\r
473 //\r
474 if (Prot != NULL) {\r
475 CoreFreePool (Prot);\r
476 }\r
1436aea4
MK
477\r
478 DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));\r
28a00297 479 }\r
480\r
481 return Status;\r
482}\r
483\r
162ed594 484/**\r
28a00297 485 Installs a list of protocol interface into the boot services environment.\r
486 This function calls InstallProtocolInterface() in a loop. If any error\r
162ed594 487 occures all the protocols added by this function are removed. This is\r
28a00297 488 basically a lib function to save space.\r
489\r
4a23eaa9
RN
490 @param Handle The pointer to a handle to install the new\r
491 protocol interfaces on, or a pointer to NULL\r
492 if a new handle is to be allocated.\r
022c6d45 493 @param ... EFI_GUID followed by protocol instance. A NULL\r
494 terminates the list. The pairs are the\r
495 arguments to InstallProtocolInterface(). All the\r
496 protocols are added to Handle.\r
28a00297 497\r
5a7b9bbe
SQ
498 @retval EFI_SUCCESS All the protocol interface was installed.\r
499 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.\r
500 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in\r
501 the handle database.\r
022c6d45 502 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
5a7b9bbe 503 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.\r
28a00297 504\r
162ed594 505**/\r
506EFI_STATUS\r
507EFIAPI\r
508CoreInstallMultipleProtocolInterfaces (\r
1436aea4 509 IN OUT EFI_HANDLE *Handle,\r
162ed594 510 ...\r
511 )\r
28a00297 512{\r
162ed594 513 VA_LIST Args;\r
28a00297 514 EFI_STATUS Status;\r
515 EFI_GUID *Protocol;\r
516 VOID *Interface;\r
517 EFI_TPL OldTpl;\r
518 UINTN Index;\r
519 EFI_HANDLE OldHandle;\r
520 EFI_HANDLE DeviceHandle;\r
521 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
022c6d45 522\r
28a00297 523 if (Handle == NULL) {\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
022c6d45 526\r
527 //\r
528 // Syncronize with notifcations.\r
28a00297 529 //\r
1436aea4 530 OldTpl = CoreRaiseTpl (TPL_NOTIFY);\r
28a00297 531 OldHandle = *Handle;\r
532\r
533 //\r
534 // Check for duplicate device path and install the protocol interfaces\r
535 //\r
162ed594 536 VA_START (Args, Handle);\r
28a00297 537 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
538 //\r
539 // If protocol is NULL, then it's the end of the list\r
540 //\r
162ed594 541 Protocol = VA_ARG (Args, EFI_GUID *);\r
28a00297 542 if (Protocol == NULL) {\r
543 break;\r
544 }\r
545\r
162ed594 546 Interface = VA_ARG (Args, VOID *);\r
28a00297 547\r
548 //\r
549 // Make sure you are installing on top a device path that has already been added.\r
550 //\r
551 if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {\r
552 DeviceHandle = NULL;\r
553 DevicePath = Interface;\r
1436aea4
MK
554 Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);\r
555 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd (DevicePath)) {\r
28a00297 556 Status = EFI_ALREADY_STARTED;\r
557 continue;\r
558 }\r
559 }\r
022c6d45 560\r
28a00297 561 //\r
562 // Install it\r
563 //\r
564 Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
565 }\r
1436aea4 566\r
a70c0fd8 567 VA_END (Args);\r
022c6d45 568\r
28a00297 569 //\r
570 // If there was an error, remove all the interfaces that were installed without any errors\r
571 //\r
572 if (EFI_ERROR (Status)) {\r
573 //\r
574 // Reset the va_arg back to the first argument.\r
575 //\r
162ed594 576 VA_START (Args, Handle);\r
1436aea4
MK
577 for ( ; Index > 1; Index--) {\r
578 Protocol = VA_ARG (Args, EFI_GUID *);\r
162ed594 579 Interface = VA_ARG (Args, VOID *);\r
28a00297 580 CoreUninstallProtocolInterface (*Handle, Protocol, Interface);\r
022c6d45 581 }\r
1436aea4 582\r
a70c0fd8 583 VA_END (Args);\r
d1102dba 584\r
28a00297 585 *Handle = OldHandle;\r
586 }\r
587\r
588 //\r
589 // Done\r
590 //\r
591 CoreRestoreTpl (OldTpl);\r
592 return Status;\r
593}\r
594\r
162ed594 595/**\r
28a00297 596 Attempts to disconnect all drivers that are using the protocol interface being queried.\r
597 If failed, reconnect all drivers disconnected.\r
162ed594 598 Note: This function doesn't do parameters checking, it's caller's responsibility\r
599 to pass in valid parameters.\r
28a00297 600\r
022c6d45 601 @param UserHandle The handle on which the protocol is installed\r
602 @param Prot The protocol to disconnect drivers from\r
28a00297 603\r
022c6d45 604 @retval EFI_SUCCESS Drivers using the protocol interface are all\r
605 disconnected\r
162ed594 606 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers\r
28a00297 607\r
162ed594 608**/\r
609EFI_STATUS\r
610CoreDisconnectControllersUsingProtocolInterface (\r
1436aea4
MK
611 IN EFI_HANDLE UserHandle,\r
612 IN PROTOCOL_INTERFACE *Prot\r
162ed594 613 )\r
28a00297 614{\r
1436aea4
MK
615 EFI_STATUS Status;\r
616 BOOLEAN ItemFound;\r
617 LIST_ENTRY *Link;\r
618 OPEN_PROTOCOL_DATA *OpenData;\r
28a00297 619\r
620 Status = EFI_SUCCESS;\r
022c6d45 621\r
28a00297 622 //\r
623 // Attempt to disconnect all drivers from this protocol interface\r
624 //\r
625 do {\r
626 ItemFound = FALSE;\r
5fc3889b 627 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
28a00297 628 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
6e536468 629 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
28a00297 630 CoreReleaseProtocolLock ();\r
631 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
632 CoreAcquireProtocolLock ();\r
5fc3889b
RN
633 if (!EFI_ERROR (Status)) {\r
634 ItemFound = TRUE;\r
28a00297 635 }\r
1436aea4 636\r
5fc3889b 637 break;\r
28a00297 638 }\r
639 }\r
640 } while (ItemFound);\r
641\r
642 if (!EFI_ERROR (Status)) {\r
643 //\r
644 // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items\r
645 //\r
5fc3889b
RN
646 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {\r
647 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
648 if ((OpenData->Attributes &\r
1436aea4
MK
649 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0)\r
650 {\r
5fc3889b
RN
651 Link = RemoveEntryList (&OpenData->Link);\r
652 Prot->OpenListCount--;\r
653 CoreFreePool (OpenData);\r
654 } else {\r
655 Link = Link->ForwardLink;\r
28a00297 656 }\r
5fc3889b 657 }\r
28a00297 658 }\r
659\r
660 //\r
661 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error\r
662 //\r
663 if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {\r
664 CoreReleaseProtocolLock ();\r
665 CoreConnectController (UserHandle, NULL, NULL, TRUE);\r
666 CoreAcquireProtocolLock ();\r
667 Status = EFI_ACCESS_DENIED;\r
668 }\r
669\r
670 return Status;\r
671}\r
672\r
162ed594 673/**\r
674 Uninstalls all instances of a protocol:interfacer from a handle.\r
675 If the last protocol interface is remove from the handle, the\r
676 handle is freed.\r
677\r
022c6d45 678 @param UserHandle The handle to remove the protocol handler from\r
679 @param Protocol The protocol, of protocol:interface, to remove\r
680 @param Interface The interface, of protocol:interface, to remove\r
162ed594 681\r
022c6d45 682 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
162ed594 683 @retval EFI_SUCCESS Protocol interface successfully uninstalled.\r
684\r
685**/\r
28a00297 686EFI_STATUS\r
687EFIAPI\r
688CoreUninstallProtocolInterface (\r
1436aea4
MK
689 IN EFI_HANDLE UserHandle,\r
690 IN EFI_GUID *Protocol,\r
691 IN VOID *Interface\r
28a00297 692 )\r
28a00297 693{\r
1436aea4
MK
694 EFI_STATUS Status;\r
695 IHANDLE *Handle;\r
696 PROTOCOL_INTERFACE *Prot;\r
28a00297 697\r
698 //\r
699 // Check that Protocol is valid\r
700 //\r
701 if (Protocol == NULL) {\r
702 return EFI_INVALID_PARAMETER;\r
703 }\r
704\r
a7fcab7a
HM
705 //\r
706 // Lock the protocol database\r
707 //\r
708 CoreAcquireProtocolLock ();\r
709\r
28a00297 710 //\r
711 // Check that UserHandle is a valid handle\r
712 //\r
713 Status = CoreValidateHandle (UserHandle);\r
714 if (EFI_ERROR (Status)) {\r
a7fcab7a 715 goto Done;\r
28a00297 716 }\r
717\r
28a00297 718 //\r
719 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database\r
720 //\r
721 Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);\r
722 if (Prot == NULL) {\r
723 Status = EFI_NOT_FOUND;\r
724 goto Done;\r
725 }\r
726\r
727 //\r
728 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed\r
729 //\r
730 Status = CoreDisconnectControllersUsingProtocolInterface (\r
731 UserHandle,\r
732 Prot\r
733 );\r
734 if (EFI_ERROR (Status)) {\r
735 //\r
736 // One or more drivers refused to release, so return the error\r
737 //\r
738 goto Done;\r
739 }\r
740\r
741 //\r
742 // Remove the protocol interface from the protocol\r
743 //\r
744 Status = EFI_NOT_FOUND;\r
745 Handle = (IHANDLE *)UserHandle;\r
746 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);\r
747\r
748 if (Prot != NULL) {\r
749 //\r
750 // Update the Key to show that the handle has been created/modified\r
751 //\r
752 gHandleDatabaseKey++;\r
753 Handle->Key = gHandleDatabaseKey;\r
022c6d45 754\r
28a00297 755 //\r
756 // Remove the protocol interface from the handle\r
757 //\r
758 RemoveEntryList (&Prot->Link);\r
759\r
760 //\r
761 // Free the memory\r
762 //\r
763 Prot->Signature = 0;\r
764 CoreFreePool (Prot);\r
765 Status = EFI_SUCCESS;\r
766 }\r
767\r
768 //\r
769 // If there are no more handlers for the handle, free the handle\r
770 //\r
771 if (IsListEmpty (&Handle->Protocols)) {\r
772 Handle->Signature = 0;\r
773 RemoveEntryList (&Handle->AllHandles);\r
774 CoreFreePool (Handle);\r
775 }\r
776\r
022c6d45 777Done:\r
28a00297 778 //\r
779 // Done, unlock the database and return\r
780 //\r
781 CoreReleaseProtocolLock ();\r
782 return Status;\r
783}\r
784\r
162ed594 785/**\r
786 Uninstalls a list of protocol interface in the boot services environment.\r
0997352d 787 This function calls UninstallProtocolInterface() in a loop. This is\r
162ed594 788 basically a lib function to save space.\r
789\r
0997352d
HS
790 If any errors are generated while the protocol interfaces are being\r
791 uninstalled, then the protocol interfaces uninstalled prior to the error will\r
792 be reinstalled and EFI_INVALID_PARAMETER will be returned.\r
793\r
794 @param Handle The handle to uninstall the protocol interfaces\r
795 from.\r
022c6d45 796 @param ... EFI_GUID followed by protocol instance. A NULL\r
0997352d 797 terminates the list. The pairs are the\r
022c6d45 798 arguments to UninstallProtocolInterface(). All\r
799 the protocols are added to Handle.\r
162ed594 800\r
0997352d
HS
801 @retval EFI_SUCCESS if all protocol interfaces where uninstalled.\r
802 @retval EFI_INVALID_PARAMETER if any protocol interface could not be\r
803 uninstalled and an attempt was made to\r
804 reinstall previously uninstalled protocol\r
805 interfaces.\r
162ed594 806**/\r
28a00297 807EFI_STATUS\r
808EFIAPI\r
809CoreUninstallMultipleProtocolInterfaces (\r
1436aea4 810 IN EFI_HANDLE Handle,\r
28a00297 811 ...\r
812 )\r
28a00297 813{\r
1436aea4
MK
814 EFI_STATUS Status;\r
815 VA_LIST Args;\r
816 EFI_GUID *Protocol;\r
817 VOID *Interface;\r
818 UINTN Index;\r
28a00297 819\r
162ed594 820 VA_START (Args, Handle);\r
28a00297 821 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {\r
822 //\r
823 // If protocol is NULL, then it's the end of the list\r
824 //\r
162ed594 825 Protocol = VA_ARG (Args, EFI_GUID *);\r
28a00297 826 if (Protocol == NULL) {\r
827 break;\r
828 }\r
829\r
162ed594 830 Interface = VA_ARG (Args, VOID *);\r
28a00297 831\r
832 //\r
833 // Uninstall it\r
834 //\r
835 Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);\r
836 }\r
1436aea4 837\r
a70c0fd8 838 VA_END (Args);\r
28a00297 839\r
840 //\r
841 // If there was an error, add all the interfaces that were\r
842 // uninstalled without any errors\r
843 //\r
844 if (EFI_ERROR (Status)) {\r
845 //\r
846 // Reset the va_arg back to the first argument.\r
847 //\r
162ed594 848 VA_START (Args, Handle);\r
1436aea4
MK
849 for ( ; Index > 1; Index--) {\r
850 Protocol = VA_ARG (Args, EFI_GUID *);\r
851 Interface = VA_ARG (Args, VOID *);\r
28a00297 852 CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);\r
022c6d45 853 }\r
1436aea4 854\r
a70c0fd8 855 VA_END (Args);\r
0997352d 856 Status = EFI_INVALID_PARAMETER;\r
28a00297 857 }\r
858\r
859 return Status;\r
022c6d45 860}\r
28a00297 861\r
162ed594 862/**\r
863 Locate a certain GUID protocol interface in a Handle's protocols.\r
864\r
022c6d45 865 @param UserHandle The handle to obtain the protocol interface on\r
866 @param Protocol The GUID of the protocol\r
162ed594 867\r
868 @return The requested protocol interface for the handle\r
869\r
870**/\r
28a00297 871PROTOCOL_INTERFACE *\r
872CoreGetProtocolInterface (\r
1436aea4
MK
873 IN EFI_HANDLE UserHandle,\r
874 IN EFI_GUID *Protocol\r
28a00297 875 )\r
28a00297 876{\r
877 EFI_STATUS Status;\r
878 PROTOCOL_ENTRY *ProtEntry;\r
879 PROTOCOL_INTERFACE *Prot;\r
880 IHANDLE *Handle;\r
881 LIST_ENTRY *Link;\r
882\r
883 Status = CoreValidateHandle (UserHandle);\r
884 if (EFI_ERROR (Status)) {\r
885 return NULL;\r
886 }\r
022c6d45 887\r
28a00297 888 Handle = (IHANDLE *)UserHandle;\r
889\r
890 //\r
891 // Look at each protocol interface for a match\r
892 //\r
893 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
1436aea4 894 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
28a00297 895 ProtEntry = Prot->Protocol;\r
896 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {\r
897 return Prot;\r
898 }\r
899 }\r
1436aea4 900\r
28a00297 901 return NULL;\r
902}\r
903\r
162ed594 904/**\r
905 Queries a handle to determine if it supports a specified protocol.\r
906\r
022c6d45 907 @param UserHandle The handle being queried.\r
908 @param Protocol The published unique identifier of the protocol.\r
909 @param Interface Supplies the address where a pointer to the\r
910 corresponding Protocol Interface is returned.\r
162ed594 911\r
11074aab 912 @retval EFI_SUCCESS The interface information for the specified protocol was returned.\r
913 @retval EFI_UNSUPPORTED The device does not support the specified protocol.\r
284ee2e8 914 @retval EFI_INVALID_PARAMETER Handle is NULL..\r
11074aab 915 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
916 @retval EFI_INVALID_PARAMETER Interface is NULL.\r
162ed594 917\r
918**/\r
28a00297 919EFI_STATUS\r
920EFIAPI\r
921CoreHandleProtocol (\r
1436aea4
MK
922 IN EFI_HANDLE UserHandle,\r
923 IN EFI_GUID *Protocol,\r
924 OUT VOID **Interface\r
28a00297 925 )\r
28a00297 926{\r
927 return CoreOpenProtocol (\r
1436aea4
MK
928 UserHandle,\r
929 Protocol,\r
930 Interface,\r
931 gDxeCoreImageHandle,\r
932 NULL,\r
933 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL\r
934 );\r
28a00297 935}\r
936\r
162ed594 937/**\r
938 Locates the installed protocol handler for the handle, and\r
939 invokes it to obtain the protocol interface. Usage information\r
940 is registered in the protocol data base.\r
941\r
022c6d45 942 @param UserHandle The handle to obtain the protocol interface on\r
943 @param Protocol The ID of the protocol\r
944 @param Interface The location to return the protocol interface\r
945 @param ImageHandle The handle of the Image that is opening the\r
946 protocol interface specified by Protocol and\r
947 Interface.\r
948 @param ControllerHandle The controller handle that is requiring this\r
949 interface.\r
950 @param Attributes The open mode of the protocol interface\r
951 specified by Handle and Protocol.\r
952\r
953 @retval EFI_INVALID_PARAMETER Protocol is NULL.\r
162ed594 954 @retval EFI_SUCCESS Get the protocol interface.\r
955\r
956**/\r
28a00297 957EFI_STATUS\r
958EFIAPI\r
959CoreOpenProtocol (\r
1436aea4
MK
960 IN EFI_HANDLE UserHandle,\r
961 IN EFI_GUID *Protocol,\r
962 OUT VOID **Interface OPTIONAL,\r
963 IN EFI_HANDLE ImageHandle,\r
964 IN EFI_HANDLE ControllerHandle,\r
965 IN UINT32 Attributes\r
28a00297 966 )\r
28a00297 967{\r
968 EFI_STATUS Status;\r
969 PROTOCOL_INTERFACE *Prot;\r
970 LIST_ENTRY *Link;\r
971 OPEN_PROTOCOL_DATA *OpenData;\r
972 BOOLEAN ByDriver;\r
973 BOOLEAN Exclusive;\r
974 BOOLEAN Disconnect;\r
975 BOOLEAN ExactMatch;\r
976\r
977 //\r
978 // Check for invalid Protocol\r
979 //\r
980 if (Protocol == NULL) {\r
981 return EFI_INVALID_PARAMETER;\r
982 }\r
983\r
984 //\r
985 // Check for invalid Interface\r
986 //\r
89f7f2cd
AK
987 if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {\r
988 return EFI_INVALID_PARAMETER;\r
28a00297 989 }\r
022c6d45 990\r
a7fcab7a
HM
991 //\r
992 // Lock the protocol database\r
993 //\r
994 CoreAcquireProtocolLock ();\r
995\r
28a00297 996 //\r
997 // Check for invalid UserHandle\r
998 //\r
999 Status = CoreValidateHandle (UserHandle);\r
1000 if (EFI_ERROR (Status)) {\r
a7fcab7a 1001 goto Done;\r
28a00297 1002 }\r
1003\r
1004 //\r
1005 // Check for invalid Attributes\r
1006 //\r
1007 switch (Attributes) {\r
1436aea4
MK
1008 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:\r
1009 Status = CoreValidateHandle (ImageHandle);\r
1010 if (EFI_ERROR (Status)) {\r
1011 goto Done;\r
1012 }\r
1013\r
1014 Status = CoreValidateHandle (ControllerHandle);\r
1015 if (EFI_ERROR (Status)) {\r
1016 goto Done;\r
1017 }\r
1018\r
1019 if (UserHandle == ControllerHandle) {\r
1020 Status = EFI_INVALID_PARAMETER;\r
1021 goto Done;\r
1022 }\r
1023\r
1024 break;\r
1025 case EFI_OPEN_PROTOCOL_BY_DRIVER:\r
1026 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
1027 Status = CoreValidateHandle (ImageHandle);\r
1028 if (EFI_ERROR (Status)) {\r
1029 goto Done;\r
1030 }\r
1031\r
1032 Status = CoreValidateHandle (ControllerHandle);\r
1033 if (EFI_ERROR (Status)) {\r
1034 goto Done;\r
1035 }\r
1036\r
1037 break;\r
1038 case EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
1039 Status = CoreValidateHandle (ImageHandle);\r
1040 if (EFI_ERROR (Status)) {\r
1041 goto Done;\r
1042 }\r
1043\r
1044 break;\r
1045 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:\r
1046 case EFI_OPEN_PROTOCOL_GET_PROTOCOL:\r
1047 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:\r
1048 break;\r
1049 default:\r
a7fcab7a
HM
1050 Status = EFI_INVALID_PARAMETER;\r
1051 goto Done;\r
28a00297 1052 }\r
1053\r
28a00297 1054 //\r
1055 // Look at each protocol interface for a match\r
1056 //\r
1057 Prot = CoreGetProtocolInterface (UserHandle, Protocol);\r
1058 if (Prot == NULL) {\r
1059 Status = EFI_UNSUPPORTED;\r
1060 goto Done;\r
1061 }\r
1062\r
28a00297 1063 Status = EFI_SUCCESS;\r
1064\r
1436aea4
MK
1065 ByDriver = FALSE;\r
1066 Exclusive = FALSE;\r
28a00297 1067 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1436aea4 1068 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
022c6d45 1069 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&\r
28a00297 1070 (OpenData->Attributes == Attributes) &&\r
1071 (OpenData->ControllerHandle == ControllerHandle));\r
6e536468 1072 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
28a00297 1073 ByDriver = TRUE;\r
1074 if (ExactMatch) {\r
1075 Status = EFI_ALREADY_STARTED;\r
1076 goto Done;\r
1077 }\r
1078 }\r
1436aea4 1079\r
6e536468 1080 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {\r
28a00297 1081 Exclusive = TRUE;\r
1082 } else if (ExactMatch) {\r
1083 OpenData->OpenCount++;\r
1084 Status = EFI_SUCCESS;\r
1085 goto Done;\r
1086 }\r
1087 }\r
1088\r
1089 //\r
1090 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)\r
1091 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)\r
1092 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)\r
1093 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)\r
1094 //\r
1095\r
1096 switch (Attributes) {\r
1436aea4
MK
1097 case EFI_OPEN_PROTOCOL_BY_DRIVER:\r
1098 if (Exclusive || ByDriver) {\r
1099 Status = EFI_ACCESS_DENIED;\r
1100 goto Done;\r
1101 }\r
1102\r
1103 break;\r
1104 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
1105 case EFI_OPEN_PROTOCOL_EXCLUSIVE:\r
1106 if (Exclusive) {\r
1107 Status = EFI_ACCESS_DENIED;\r
1108 goto Done;\r
1109 }\r
1110\r
1111 if (ByDriver) {\r
1112 do {\r
1113 Disconnect = FALSE;\r
1114 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {\r
1115 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1116 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {\r
1117 Disconnect = TRUE;\r
1118 CoreReleaseProtocolLock ();\r
1119 Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);\r
1120 CoreAcquireProtocolLock ();\r
1121 if (EFI_ERROR (Status)) {\r
1122 Status = EFI_ACCESS_DENIED;\r
1123 goto Done;\r
1124 } else {\r
1125 break;\r
1126 }\r
28a00297 1127 }\r
1128 }\r
1436aea4
MK
1129 } while (Disconnect);\r
1130 }\r
1131\r
1132 break;\r
1133 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:\r
1134 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:\r
1135 case EFI_OPEN_PROTOCOL_GET_PROTOCOL:\r
1136 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:\r
1137 break;\r
28a00297 1138 }\r
1139\r
1140 if (ImageHandle == NULL) {\r
1141 Status = EFI_SUCCESS;\r
1142 goto Done;\r
1143 }\r
1436aea4 1144\r
28a00297 1145 //\r
1146 // Create new entry\r
1147 //\r
1436aea4 1148 OpenData = AllocatePool (sizeof (OPEN_PROTOCOL_DATA));\r
28a00297 1149 if (OpenData == NULL) {\r
1150 Status = EFI_OUT_OF_RESOURCES;\r
1151 } else {\r
1436aea4
MK
1152 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;\r
1153 OpenData->AgentHandle = ImageHandle;\r
1154 OpenData->ControllerHandle = ControllerHandle;\r
1155 OpenData->Attributes = Attributes;\r
1156 OpenData->OpenCount = 1;\r
28a00297 1157 InsertTailList (&Prot->OpenList, &OpenData->Link);\r
1158 Prot->OpenListCount++;\r
1159 Status = EFI_SUCCESS;\r
1160 }\r
1161\r
1162Done:\r
89f7f2cd
AK
1163\r
1164 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {\r
1165 //\r
1166 // Keep Interface unmodified in case of any Error\r
1167 // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.\r
1168 //\r
1436aea4 1169 if (!EFI_ERROR (Status) || (Status == EFI_ALREADY_STARTED)) {\r
ab3f3d70
HW
1170 //\r
1171 // According to above logic, if 'Prot' is NULL, then the 'Status' must be\r
1172 // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'\r
1173 // must be not NULL.\r
1174 //\r
1175 // The ASSERT here is for addressing a false positive NULL pointer\r
1176 // dereference issue raised from static analysis.\r
1177 //\r
1178 ASSERT (Prot != NULL);\r
89f7f2cd
AK
1179 //\r
1180 // EFI_ALREADY_STARTED is not an error for bus driver.\r
1181 // Return the corresponding protocol interface.\r
1182 //\r
1183 *Interface = Prot->Interface;\r
1184 } else if (Status == EFI_UNSUPPORTED) {\r
1185 //\r
1186 // Return NULL Interface if Unsupported Protocol.\r
1187 //\r
1188 *Interface = NULL;\r
1189 }\r
1190 }\r
1191\r
28a00297 1192 //\r
89f7f2cd 1193 // Done. Release the database lock and return\r
28a00297 1194 //\r
1195 CoreReleaseProtocolLock ();\r
1196 return Status;\r
1197}\r
1198\r
162ed594 1199/**\r
1200 Closes a protocol on a handle that was opened using OpenProtocol().\r
1201\r
022c6d45 1202 @param UserHandle The handle for the protocol interface that was\r
1203 previously opened with OpenProtocol(), and is\r
1204 now being closed.\r
1205 @param Protocol The published unique identifier of the protocol.\r
1206 It is the caller's responsibility to pass in a\r
1207 valid GUID.\r
1208 @param AgentHandle The handle of the agent that is closing the\r
1209 protocol interface.\r
1210 @param ControllerHandle If the agent that opened a protocol is a driver\r
1211 that follows the EFI Driver Model, then this\r
1212 parameter is the controller handle that required\r
1213 the protocol interface. If the agent does not\r
1214 follow the EFI Driver Model, then this parameter\r
1215 is optional and may be NULL.\r
1216\r
1217 @retval EFI_SUCCESS The protocol instance was closed.\r
1218 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a\r
1219 valid EFI_HANDLE.\r
1220 @retval EFI_NOT_FOUND Can not find the specified protocol or\r
162ed594 1221 AgentHandle.\r
1222\r
1223**/\r
28a00297 1224EFI_STATUS\r
1225EFIAPI\r
1226CoreCloseProtocol (\r
1436aea4
MK
1227 IN EFI_HANDLE UserHandle,\r
1228 IN EFI_GUID *Protocol,\r
1229 IN EFI_HANDLE AgentHandle,\r
1230 IN EFI_HANDLE ControllerHandle\r
28a00297 1231 )\r
28a00297 1232{\r
1233 EFI_STATUS Status;\r
1234 PROTOCOL_INTERFACE *ProtocolInterface;\r
1235 LIST_ENTRY *Link;\r
1236 OPEN_PROTOCOL_DATA *OpenData;\r
1237\r
a7fcab7a
HM
1238 //\r
1239 // Lock the protocol database\r
1240 //\r
1241 CoreAcquireProtocolLock ();\r
1242\r
28a00297 1243 //\r
1244 // Check for invalid parameters\r
1245 //\r
1246 Status = CoreValidateHandle (UserHandle);\r
1247 if (EFI_ERROR (Status)) {\r
a7fcab7a 1248 goto Done;\r
28a00297 1249 }\r
1436aea4 1250\r
28a00297 1251 Status = CoreValidateHandle (AgentHandle);\r
1252 if (EFI_ERROR (Status)) {\r
a7fcab7a 1253 goto Done;\r
28a00297 1254 }\r
1436aea4 1255\r
4008328a 1256 if (ControllerHandle != NULL) {\r
28a00297 1257 Status = CoreValidateHandle (ControllerHandle);\r
1258 if (EFI_ERROR (Status)) {\r
a7fcab7a 1259 goto Done;\r
28a00297 1260 }\r
1261 }\r
1436aea4 1262\r
28a00297 1263 if (Protocol == NULL) {\r
a7fcab7a
HM
1264 Status = EFI_INVALID_PARAMETER;\r
1265 goto Done;\r
28a00297 1266 }\r
1267\r
28a00297 1268 //\r
1269 // Look at each protocol interface for a match\r
1270 //\r
1436aea4 1271 Status = EFI_NOT_FOUND;\r
28a00297 1272 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1273 if (ProtocolInterface == NULL) {\r
1274 goto Done;\r
1275 }\r
1276\r
1277 //\r
1278 // Walk the Open data base looking for AgentHandle\r
1279 //\r
1280 Link = ProtocolInterface->OpenList.ForwardLink;\r
1281 while (Link != &ProtocolInterface->OpenList) {\r
1282 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1436aea4 1283 Link = Link->ForwardLink;\r
28a00297 1284 if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {\r
1436aea4
MK
1285 RemoveEntryList (&OpenData->Link);\r
1286 ProtocolInterface->OpenListCount--;\r
1287 CoreFreePool (OpenData);\r
1288 Status = EFI_SUCCESS;\r
28a00297 1289 }\r
1290 }\r
1291\r
1292Done:\r
1293 //\r
1294 // Done. Release the database lock and return.\r
1295 //\r
1296 CoreReleaseProtocolLock ();\r
1297 return Status;\r
1298}\r
1299\r
162ed594 1300/**\r
1301 Return information about Opened protocols in the system\r
1302\r
022c6d45 1303 @param UserHandle The handle to close the protocol interface on\r
1304 @param Protocol The ID of the protocol\r
11074aab 1305 @param EntryBuffer A pointer to a buffer of open protocol information in the\r
1306 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.\r
162ed594 1307 @param EntryCount Number of EntryBuffer entries\r
1308\r
d1102dba 1309 @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer,\r
11074aab 1310 and the number of entries was returned EntryCount.\r
1311 @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol.\r
1312 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer.\r
1313\r
162ed594 1314**/\r
28a00297 1315EFI_STATUS\r
1316EFIAPI\r
1317CoreOpenProtocolInformation (\r
1436aea4
MK
1318 IN EFI_HANDLE UserHandle,\r
1319 IN EFI_GUID *Protocol,\r
1320 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,\r
1321 OUT UINTN *EntryCount\r
28a00297 1322 )\r
28a00297 1323{\r
1436aea4
MK
1324 EFI_STATUS Status;\r
1325 PROTOCOL_INTERFACE *ProtocolInterface;\r
1326 LIST_ENTRY *Link;\r
1327 OPEN_PROTOCOL_DATA *OpenData;\r
1328 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;\r
1329 UINTN Count;\r
1330 UINTN Size;\r
28a00297 1331\r
1332 *EntryBuffer = NULL;\r
1436aea4 1333 *EntryCount = 0;\r
28a00297 1334\r
1335 //\r
1336 // Lock the protocol database\r
1337 //\r
1338 CoreAcquireProtocolLock ();\r
1339\r
1340 //\r
1341 // Look at each protocol interface for a match\r
1342 //\r
1436aea4 1343 Status = EFI_NOT_FOUND;\r
28a00297 1344 ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);\r
1345 if (ProtocolInterface == NULL) {\r
1346 goto Done;\r
1347 }\r
1348\r
1349 //\r
1350 // Count the number of Open Entries\r
1351 //\r
022c6d45 1352 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
1436aea4
MK
1353 (Link != &ProtocolInterface->OpenList);\r
1354 Link = Link->ForwardLink )\r
1355 {\r
28a00297 1356 Count++;\r
022c6d45 1357 }\r
28a00297 1358\r
1359 ASSERT (Count == ProtocolInterface->OpenListCount);\r
1360\r
1361 if (Count == 0) {\r
1436aea4 1362 Size = sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
28a00297 1363 } else {\r
1436aea4 1364 Size = Count * sizeof (EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);\r
28a00297 1365 }\r
1366\r
9c4ac31c 1367 Buffer = AllocatePool (Size);\r
28a00297 1368 if (Buffer == NULL) {\r
1369 Status = EFI_OUT_OF_RESOURCES;\r
1370 goto Done;\r
1371 }\r
1372\r
1373 Status = EFI_SUCCESS;\r
022c6d45 1374 for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;\r
28a00297 1375 (Link != &ProtocolInterface->OpenList);\r
1436aea4
MK
1376 Link = Link->ForwardLink, Count++ )\r
1377 {\r
28a00297 1378 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);\r
1379\r
1380 Buffer[Count].AgentHandle = OpenData->AgentHandle;\r
1381 Buffer[Count].ControllerHandle = OpenData->ControllerHandle;\r
1382 Buffer[Count].Attributes = OpenData->Attributes;\r
1383 Buffer[Count].OpenCount = OpenData->OpenCount;\r
022c6d45 1384 }\r
28a00297 1385\r
1386 *EntryBuffer = Buffer;\r
1436aea4 1387 *EntryCount = Count;\r
022c6d45 1388\r
28a00297 1389Done:\r
1390 //\r
1439777e 1391 // Done. Release the database lock.\r
28a00297 1392 //\r
1393 CoreReleaseProtocolLock ();\r
1394 return Status;\r
1395}\r
1396\r
162ed594 1397/**\r
1398 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated\r
1399 from pool.\r
1400\r
022c6d45 1401 @param UserHandle The handle from which to retrieve the list of\r
1402 protocol interface GUIDs.\r
1403 @param ProtocolBuffer A pointer to the list of protocol interface GUID\r
1404 pointers that are installed on Handle.\r
1405 @param ProtocolBufferCount A pointer to the number of GUID pointers present\r
1406 in ProtocolBuffer.\r
1407\r
1408 @retval EFI_SUCCESS The list of protocol interface GUIDs installed\r
1409 on Handle was returned in ProtocolBuffer. The\r
1410 number of protocol interface GUIDs was returned\r
1411 in ProtocolBufferCount.\r
1412 @retval EFI_INVALID_PARAMETER Handle is NULL.\r
1413 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.\r
1414 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.\r
1415 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.\r
1416 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the\r
162ed594 1417 results.\r
1418\r
1419**/\r
28a00297 1420EFI_STATUS\r
1421EFIAPI\r
1422CoreProtocolsPerHandle (\r
1436aea4
MK
1423 IN EFI_HANDLE UserHandle,\r
1424 OUT EFI_GUID ***ProtocolBuffer,\r
1425 OUT UINTN *ProtocolBufferCount\r
28a00297 1426 )\r
28a00297 1427{\r
1436aea4
MK
1428 EFI_STATUS Status;\r
1429 IHANDLE *Handle;\r
1430 PROTOCOL_INTERFACE *Prot;\r
1431 LIST_ENTRY *Link;\r
1432 UINTN ProtocolCount;\r
1433 EFI_GUID **Buffer;\r
28a00297 1434\r
28a00297 1435 if (ProtocolBuffer == NULL) {\r
1436 return EFI_INVALID_PARAMETER;\r
1437 }\r
1438\r
1439 if (ProtocolBufferCount == NULL) {\r
1440 return EFI_INVALID_PARAMETER;\r
1441 }\r
1442\r
1443 *ProtocolBufferCount = 0;\r
1444\r
1445 ProtocolCount = 0;\r
1446\r
1447 CoreAcquireProtocolLock ();\r
022c6d45 1448\r
a7fcab7a
HM
1449 Status = CoreValidateHandle (UserHandle);\r
1450 if (EFI_ERROR (Status)) {\r
1451 goto Done;\r
1452 }\r
1453\r
1454 Handle = (IHANDLE *)UserHandle;\r
1455\r
28a00297 1456 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {\r
1457 ProtocolCount++;\r
1458 }\r
1459\r
1460 //\r
1461 // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE\r
1462 //\r
1463 if (ProtocolCount == 0) {\r
1464 Status = EFI_INVALID_PARAMETER;\r
1465 goto Done;\r
1466 }\r
1467\r
9c4ac31c 1468 Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);\r
28a00297 1469 if (Buffer == NULL) {\r
1470 Status = EFI_OUT_OF_RESOURCES;\r
1471 goto Done;\r
1472 }\r
1473\r
1436aea4 1474 *ProtocolBuffer = Buffer;\r
28a00297 1475 *ProtocolBufferCount = ProtocolCount;\r
1476\r
1477 for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;\r
022c6d45 1478 Link != &Handle->Protocols;\r
1436aea4
MK
1479 Link = Link->ForwardLink, ProtocolCount++)\r
1480 {\r
1481 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);\r
28a00297 1482 Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);\r
1483 }\r
1436aea4 1484\r
28a00297 1485 Status = EFI_SUCCESS;\r
1486\r
1487Done:\r
1488 CoreReleaseProtocolLock ();\r
1489 return Status;\r
1490}\r
1491\r
162ed594 1492/**\r
28a00297 1493 return handle database key.\r
1494\r
28a00297 1495\r
162ed594 1496 @return Handle database key.\r
1497\r
1498**/\r
1499UINT64\r
1500CoreGetHandleDatabaseKey (\r
1501 VOID\r
1502 )\r
28a00297 1503{\r
1504 return gHandleDatabaseKey;\r
1505}\r
1506\r
162ed594 1507/**\r
28a00297 1508 Go connect any handles that were created or modified while a image executed.\r
1509\r
022c6d45 1510 @param Key The Key to show that the handle has been\r
162ed594 1511 created/modified\r
28a00297 1512\r
162ed594 1513**/\r
1514VOID\r
1515CoreConnectHandlesByKey (\r
1516 UINT64 Key\r
1517 )\r
28a00297 1518{\r
1436aea4
MK
1519 UINTN Count;\r
1520 LIST_ENTRY *Link;\r
1521 EFI_HANDLE *HandleBuffer;\r
1522 IHANDLE *Handle;\r
1523 UINTN Index;\r
28a00297 1524\r
1525 //\r
1526 // Lock the protocol database\r
1527 //\r
1528 CoreAcquireProtocolLock ();\r
1529\r
1530 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1531 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1532 if (Handle->Key > Key) {\r
1533 Count++;\r
1534 }\r
1535 }\r
1536\r
9c4ac31c 1537 HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));\r
28a00297 1538 if (HandleBuffer == NULL) {\r
1539 CoreReleaseProtocolLock ();\r
1540 return;\r
1541 }\r
022c6d45 1542\r
28a00297 1543 for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {\r
1544 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);\r
1545 if (Handle->Key > Key) {\r
1546 HandleBuffer[Count++] = Handle;\r
1547 }\r
1548 }\r
1549\r
1550 //\r
1551 // Unlock the protocol database\r
1552 //\r
1553 CoreReleaseProtocolLock ();\r
1554\r
1555 //\r
1556 // Connect all handles whose Key value is greater than Key\r
1557 //\r
1558 for (Index = 0; Index < Count; Index++) {\r
1559 CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);\r
1560 }\r
022c6d45 1561\r
1436aea4 1562 CoreFreePool (HandleBuffer);\r
28a00297 1563}\r