123c98c9417908188207408afa3f6901b8aca826aqhuang/** @file
2162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  UEFI handle & protocol handling.
328a00297189c323096aae8e2975de94e8549613cyshang
45a7b9bbe08a5dfc8de6f5091a4b140818604d403Shumin QiuCopyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
5cd5ebaa06dca3e6ef3c464081e6defe00d358c69hhtianThis program and the accompanying materials
623c98c9417908188207408afa3f6901b8aca826aqhuangare licensed and made available under the terms and conditions of the BSD License
723c98c9417908188207408afa3f6901b8aca826aqhuangwhich accompanies this distribution.  The full text of the license may be found at
823c98c9417908188207408afa3f6901b8aca826aqhuanghttp://opensource.org/licenses/bsd-license.php
923c98c9417908188207408afa3f6901b8aca826aqhuang
1023c98c9417908188207408afa3f6901b8aca826aqhuangTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1123c98c9417908188207408afa3f6901b8aca826aqhuangWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1228a00297189c323096aae8e2975de94e8549613cyshang
13504214c4870e9183418014634268ce630eb5332algao**/
1428a00297189c323096aae8e2975de94e8549613cyshang
159c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang#include "DxeMain.h"
16ec90508b3d3ff22a698a0446cb09d551d7466045eric_tian#include "Handle.h"
1728a00297189c323096aae8e2975de94e8549613cyshang
1828a00297189c323096aae8e2975de94e8549613cyshang
1928a00297189c323096aae8e2975de94e8549613cyshang//
2028a00297189c323096aae8e2975de94e8549613cyshang// mProtocolDatabase     - A list of all protocols in the system.  (simple list for now)
2128a00297189c323096aae8e2975de94e8549613cyshang// gHandleList           - A list of all the handles in the system
2228a00297189c323096aae8e2975de94e8549613cyshang// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
2328a00297189c323096aae8e2975de94e8549613cyshang// gHandleDatabaseKey    -  The Key to show that the handle has been created/modified
2428a00297189c323096aae8e2975de94e8549613cyshang//
25e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuangLIST_ENTRY      mProtocolDatabase     = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
2658125fb3f9dda7f15a540b16595dc24dab0dd423qhuangLIST_ENTRY      gHandleList           = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
2758125fb3f9dda7f15a540b16595dc24dab0dd423qhuangEFI_LOCK        gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
2858125fb3f9dda7f15a540b16595dc24dab0dd423qhuangUINT64          gHandleDatabaseKey    = 0;
2928a00297189c323096aae8e2975de94e8549613cyshang
3028a00297189c323096aae8e2975de94e8549613cyshang
31162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
32162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
33162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Acquire lock on gProtocolDatabaseLock.
34162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
35162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
3628a00297189c323096aae8e2975de94e8549613cyshangVOID
3728a00297189c323096aae8e2975de94e8549613cyshangCoreAcquireProtocolLock (
3828a00297189c323096aae8e2975de94e8549613cyshang  VOID
3928a00297189c323096aae8e2975de94e8549613cyshang  )
4028a00297189c323096aae8e2975de94e8549613cyshang{
4128a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireLock (&gProtocolDatabaseLock);
4228a00297189c323096aae8e2975de94e8549613cyshang}
4328a00297189c323096aae8e2975de94e8549613cyshang
4428a00297189c323096aae8e2975de94e8549613cyshang
45162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
46162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
47162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Release lock on gProtocolDatabaseLock.
48162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
49162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
5028a00297189c323096aae8e2975de94e8549613cyshangVOID
5128a00297189c323096aae8e2975de94e8549613cyshangCoreReleaseProtocolLock (
5228a00297189c323096aae8e2975de94e8549613cyshang  VOID
5328a00297189c323096aae8e2975de94e8549613cyshang  )
5428a00297189c323096aae8e2975de94e8549613cyshang{
5528a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseLock (&gProtocolDatabaseLock);
5628a00297189c323096aae8e2975de94e8549613cyshang}
5728a00297189c323096aae8e2975de94e8549613cyshang
5828a00297189c323096aae8e2975de94e8549613cyshang
5928a00297189c323096aae8e2975de94e8549613cyshang
60162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
6128a00297189c323096aae8e2975de94e8549613cyshang  Check whether a handle is a valid EFI_HANDLE
6228a00297189c323096aae8e2975de94e8549613cyshang
63022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle to check
6428a00297189c323096aae8e2975de94e8549613cyshang
65022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  The handle is NULL or not a valid EFI_HANDLE.
66162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @retval EFI_SUCCESS            The handle is valid EFI_HANDLE.
6728a00297189c323096aae8e2975de94e8549613cyshang
68162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
69162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFI_STATUS
70162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreValidateHandle (
71162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN  EFI_HANDLE                UserHandle
72162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
7328a00297189c323096aae8e2975de94e8549613cyshang{
7428a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE             *Handle;
7528a00297189c323096aae8e2975de94e8549613cyshang
7628a00297189c323096aae8e2975de94e8549613cyshang  Handle = (IHANDLE *)UserHandle;
7728a00297189c323096aae8e2975de94e8549613cyshang  if (Handle == NULL) {
7828a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
7928a00297189c323096aae8e2975de94e8549613cyshang  }
8028a00297189c323096aae8e2975de94e8549613cyshang  if (Handle->Signature != EFI_HANDLE_SIGNATURE) {
8128a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
8228a00297189c323096aae8e2975de94e8549613cyshang  }
8328a00297189c323096aae8e2975de94e8549613cyshang  return EFI_SUCCESS;
8428a00297189c323096aae8e2975de94e8549613cyshang}
8528a00297189c323096aae8e2975de94e8549613cyshang
8628a00297189c323096aae8e2975de94e8549613cyshang
8728a00297189c323096aae8e2975de94e8549613cyshang
88162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
8928a00297189c323096aae8e2975de94e8549613cyshang  Finds the protocol entry for the requested protocol.
9028a00297189c323096aae8e2975de94e8549613cyshang  The gProtocolDatabaseLock must be owned
9128a00297189c323096aae8e2975de94e8549613cyshang
92022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The ID of the protocol
93022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Create                 Create a new entry if not found
9428a00297189c323096aae8e2975de94e8549613cyshang
95162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return Protocol entry
9628a00297189c323096aae8e2975de94e8549613cyshang
97162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
98162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangPROTOCOL_ENTRY  *
99162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreFindProtocolEntry (
100162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN EFI_GUID   *Protocol,
101162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN BOOLEAN    Create
102162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
10328a00297189c323096aae8e2975de94e8549613cyshang{
10428a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY          *Link;
10528a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_ENTRY      *Item;
10628a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_ENTRY      *ProtEntry;
10728a00297189c323096aae8e2975de94e8549613cyshang
10828a00297189c323096aae8e2975de94e8549613cyshang  ASSERT_LOCKED(&gProtocolDatabaseLock);
10928a00297189c323096aae8e2975de94e8549613cyshang
11028a00297189c323096aae8e2975de94e8549613cyshang  //
11128a00297189c323096aae8e2975de94e8549613cyshang  // Search the database for the matching GUID
11228a00297189c323096aae8e2975de94e8549613cyshang  //
11328a00297189c323096aae8e2975de94e8549613cyshang
11428a00297189c323096aae8e2975de94e8549613cyshang  ProtEntry = NULL;
115022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  for (Link = mProtocolDatabase.ForwardLink;
116022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang       Link != &mProtocolDatabase;
11728a00297189c323096aae8e2975de94e8549613cyshang       Link = Link->ForwardLink) {
11828a00297189c323096aae8e2975de94e8549613cyshang
11928a00297189c323096aae8e2975de94e8549613cyshang    Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
12028a00297189c323096aae8e2975de94e8549613cyshang    if (CompareGuid (&Item->ProtocolID, Protocol)) {
12128a00297189c323096aae8e2975de94e8549613cyshang
12228a00297189c323096aae8e2975de94e8549613cyshang      //
12328a00297189c323096aae8e2975de94e8549613cyshang      // This is the protocol entry
12428a00297189c323096aae8e2975de94e8549613cyshang      //
12528a00297189c323096aae8e2975de94e8549613cyshang
12628a00297189c323096aae8e2975de94e8549613cyshang      ProtEntry = Item;
12728a00297189c323096aae8e2975de94e8549613cyshang      break;
12828a00297189c323096aae8e2975de94e8549613cyshang    }
12928a00297189c323096aae8e2975de94e8549613cyshang  }
13028a00297189c323096aae8e2975de94e8549613cyshang
13128a00297189c323096aae8e2975de94e8549613cyshang  //
132022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  // If the protocol entry was not found and Create is TRUE, then
13328a00297189c323096aae8e2975de94e8549613cyshang  // allocate a new entry
134022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  //
13528a00297189c323096aae8e2975de94e8549613cyshang  if ((ProtEntry == NULL) && Create) {
1369c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    ProtEntry = AllocatePool (sizeof(PROTOCOL_ENTRY));
137022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
13828a00297189c323096aae8e2975de94e8549613cyshang    if (ProtEntry != NULL) {
13928a00297189c323096aae8e2975de94e8549613cyshang      //
14028a00297189c323096aae8e2975de94e8549613cyshang      // Initialize new protocol entry structure
14128a00297189c323096aae8e2975de94e8549613cyshang      //
14228a00297189c323096aae8e2975de94e8549613cyshang      ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
143e94a9ff7271367e649ee4f9a86da1f1bea6d112eqhuang      CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
14428a00297189c323096aae8e2975de94e8549613cyshang      InitializeListHead (&ProtEntry->Protocols);
14528a00297189c323096aae8e2975de94e8549613cyshang      InitializeListHead (&ProtEntry->Notify);
14628a00297189c323096aae8e2975de94e8549613cyshang
14728a00297189c323096aae8e2975de94e8549613cyshang      //
14828a00297189c323096aae8e2975de94e8549613cyshang      // Add it to protocol database
14928a00297189c323096aae8e2975de94e8549613cyshang      //
15028a00297189c323096aae8e2975de94e8549613cyshang      InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
15128a00297189c323096aae8e2975de94e8549613cyshang    }
15228a00297189c323096aae8e2975de94e8549613cyshang  }
15328a00297189c323096aae8e2975de94e8549613cyshang
15428a00297189c323096aae8e2975de94e8549613cyshang  return ProtEntry;
15528a00297189c323096aae8e2975de94e8549613cyshang}
15628a00297189c323096aae8e2975de94e8549613cyshang
15728a00297189c323096aae8e2975de94e8549613cyshang
158162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
159162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
160162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Finds the protocol instance for the requested handle and protocol.
161162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Note: This function doesn't do parameters checking, it's caller's responsibility
162162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  to pass in valid parameters.
163162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
164022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Handle                 The handle to search the protocol on
165022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               GUID of the protocol
166022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Interface              The interface for the protocol being searched
167162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
168162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return Protocol instance (NULL: Not found)
169162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
170162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
17128a00297189c323096aae8e2975de94e8549613cyshangPROTOCOL_INTERFACE *
17228a00297189c323096aae8e2975de94e8549613cyshangCoreFindProtocolInterface (
17328a00297189c323096aae8e2975de94e8549613cyshang  IN IHANDLE        *Handle,
17428a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_GUID       *Protocol,
17528a00297189c323096aae8e2975de94e8549613cyshang  IN VOID           *Interface
17628a00297189c323096aae8e2975de94e8549613cyshang  )
17728a00297189c323096aae8e2975de94e8549613cyshang{
17828a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE  *Prot;
17928a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_ENTRY      *ProtEntry;
18028a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY          *Link;
18128a00297189c323096aae8e2975de94e8549613cyshang
18228a00297189c323096aae8e2975de94e8549613cyshang  ASSERT_LOCKED(&gProtocolDatabaseLock);
18328a00297189c323096aae8e2975de94e8549613cyshang  Prot = NULL;
18428a00297189c323096aae8e2975de94e8549613cyshang
18528a00297189c323096aae8e2975de94e8549613cyshang  //
18628a00297189c323096aae8e2975de94e8549613cyshang  // Lookup the protocol entry for this protocol ID
18728a00297189c323096aae8e2975de94e8549613cyshang  //
18828a00297189c323096aae8e2975de94e8549613cyshang
18928a00297189c323096aae8e2975de94e8549613cyshang  ProtEntry = CoreFindProtocolEntry (Protocol, FALSE);
19028a00297189c323096aae8e2975de94e8549613cyshang  if (ProtEntry != NULL) {
19128a00297189c323096aae8e2975de94e8549613cyshang
19228a00297189c323096aae8e2975de94e8549613cyshang    //
19328a00297189c323096aae8e2975de94e8549613cyshang    // Look at each protocol interface for any matches
19428a00297189c323096aae8e2975de94e8549613cyshang    //
19528a00297189c323096aae8e2975de94e8549613cyshang    for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) {
19628a00297189c323096aae8e2975de94e8549613cyshang
19728a00297189c323096aae8e2975de94e8549613cyshang      //
19828a00297189c323096aae8e2975de94e8549613cyshang      // If this protocol interface matches, remove it
19928a00297189c323096aae8e2975de94e8549613cyshang      //
20028a00297189c323096aae8e2975de94e8549613cyshang      Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
20128a00297189c323096aae8e2975de94e8549613cyshang      if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) {
20228a00297189c323096aae8e2975de94e8549613cyshang        break;
20328a00297189c323096aae8e2975de94e8549613cyshang      }
20428a00297189c323096aae8e2975de94e8549613cyshang
20528a00297189c323096aae8e2975de94e8549613cyshang      Prot = NULL;
20628a00297189c323096aae8e2975de94e8549613cyshang    }
20728a00297189c323096aae8e2975de94e8549613cyshang  }
20828a00297189c323096aae8e2975de94e8549613cyshang
20928a00297189c323096aae8e2975de94e8549613cyshang  return Prot;
21028a00297189c323096aae8e2975de94e8549613cyshang}
21128a00297189c323096aae8e2975de94e8549613cyshang
21228a00297189c323096aae8e2975de94e8549613cyshang
213162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
21428a00297189c323096aae8e2975de94e8549613cyshang  Removes an event from a register protocol notify list on a protocol.
21528a00297189c323096aae8e2975de94e8549613cyshang
216022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Event                  The event to search for in the protocol
217022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 database.
21828a00297189c323096aae8e2975de94e8549613cyshang
219162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return EFI_SUCCESS   if the event was found and removed.
220162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return EFI_NOT_FOUND if the event was not found in the protocl database.
22128a00297189c323096aae8e2975de94e8549613cyshang
222162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
223162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFI_STATUS
224162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreUnregisterProtocolNotifyEvent (
225162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN EFI_EVENT      Event
226162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
22728a00297189c323096aae8e2975de94e8549613cyshang{
22828a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY         *Link;
22928a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_ENTRY     *ProtEntry;
23028a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY         *NotifyLink;
23128a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_NOTIFY    *ProtNotify;
23228a00297189c323096aae8e2975de94e8549613cyshang
23328a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
23428a00297189c323096aae8e2975de94e8549613cyshang
235022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  for ( Link =  mProtocolDatabase.ForwardLink;
236022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang        Link != &mProtocolDatabase;
23728a00297189c323096aae8e2975de94e8549613cyshang        Link =  Link->ForwardLink) {
23828a00297189c323096aae8e2975de94e8549613cyshang
23928a00297189c323096aae8e2975de94e8549613cyshang    ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
24028a00297189c323096aae8e2975de94e8549613cyshang
241022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang    for ( NotifyLink =  ProtEntry->Notify.ForwardLink;
242022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          NotifyLink != &ProtEntry->Notify;
24328a00297189c323096aae8e2975de94e8549613cyshang          NotifyLink =  NotifyLink->ForwardLink) {
24428a00297189c323096aae8e2975de94e8549613cyshang
24528a00297189c323096aae8e2975de94e8549613cyshang      ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
24628a00297189c323096aae8e2975de94e8549613cyshang
24728a00297189c323096aae8e2975de94e8549613cyshang      if (ProtNotify->Event == Event) {
24828a00297189c323096aae8e2975de94e8549613cyshang        RemoveEntryList(&ProtNotify->Link);
24928a00297189c323096aae8e2975de94e8549613cyshang        CoreFreePool(ProtNotify);
25028a00297189c323096aae8e2975de94e8549613cyshang        CoreReleaseProtocolLock ();
25128a00297189c323096aae8e2975de94e8549613cyshang        return EFI_SUCCESS;
25228a00297189c323096aae8e2975de94e8549613cyshang      }
25328a00297189c323096aae8e2975de94e8549613cyshang    }
25428a00297189c323096aae8e2975de94e8549613cyshang  }
25528a00297189c323096aae8e2975de94e8549613cyshang
25628a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
25728a00297189c323096aae8e2975de94e8549613cyshang  return EFI_NOT_FOUND;
25828a00297189c323096aae8e2975de94e8549613cyshang}
25928a00297189c323096aae8e2975de94e8549613cyshang
26028a00297189c323096aae8e2975de94e8549613cyshang
26128a00297189c323096aae8e2975de94e8549613cyshang
262162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
26328a00297189c323096aae8e2975de94e8549613cyshang  Removes all the events in the protocol database that match Event.
26428a00297189c323096aae8e2975de94e8549613cyshang
265022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Event                  The event to search for in the protocol
266022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 database.
26728a00297189c323096aae8e2975de94e8549613cyshang
268162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return EFI_SUCCESS when done searching the entire database.
26928a00297189c323096aae8e2975de94e8549613cyshang
270162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
271162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFI_STATUS
272162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreUnregisterProtocolNotify (
273162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN EFI_EVENT      Event
274162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
27528a00297189c323096aae8e2975de94e8549613cyshang{
27628a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS       Status;
27728a00297189c323096aae8e2975de94e8549613cyshang
27828a00297189c323096aae8e2975de94e8549613cyshang  do {
27928a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreUnregisterProtocolNotifyEvent (Event);
28028a00297189c323096aae8e2975de94e8549613cyshang  } while (!EFI_ERROR (Status));
28128a00297189c323096aae8e2975de94e8549613cyshang
28228a00297189c323096aae8e2975de94e8549613cyshang  return EFI_SUCCESS;
28328a00297189c323096aae8e2975de94e8549613cyshang}
28428a00297189c323096aae8e2975de94e8549613cyshang
28528a00297189c323096aae8e2975de94e8549613cyshang
28628a00297189c323096aae8e2975de94e8549613cyshang
287162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
288162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
289162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Wrapper function to CoreInstallProtocolInterfaceNotify.  This is the public API which
290162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Calls the private one which contains a BOOLEAN parameter for notifications
291162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
292022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle to install the protocol handler on,
293022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 or NULL if a new handle is to be allocated
294022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The protocol to add to the handle
295022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  InterfaceType          Indicates whether Interface is supplied in
296022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 native form.
297022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Interface              The interface for the protocol being added
298162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
299162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return Status code
300162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
301162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
30228a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
30328a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
30428a00297189c323096aae8e2975de94e8549613cyshangCoreInstallProtocolInterface (
30528a00297189c323096aae8e2975de94e8549613cyshang  IN OUT EFI_HANDLE     *UserHandle,
30628a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_GUID           *Protocol,
30728a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_INTERFACE_TYPE InterfaceType,
30828a00297189c323096aae8e2975de94e8549613cyshang  IN VOID               *Interface
30928a00297189c323096aae8e2975de94e8549613cyshang  )
31028a00297189c323096aae8e2975de94e8549613cyshang{
31128a00297189c323096aae8e2975de94e8549613cyshang  return CoreInstallProtocolInterfaceNotify (
312022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang            UserHandle,
313022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang            Protocol,
314022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang            InterfaceType,
315022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang            Interface,
31628a00297189c323096aae8e2975de94e8549613cyshang            TRUE
31728a00297189c323096aae8e2975de94e8549613cyshang            );
31828a00297189c323096aae8e2975de94e8549613cyshang}
31928a00297189c323096aae8e2975de94e8549613cyshang
320162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
321162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
322162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Installs a protocol interface into the boot services environment.
323162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
324022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle to install the protocol handler on,
325022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 or NULL if a new handle is to be allocated
326022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The protocol to add to the handle
327022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  InterfaceType          Indicates whether Interface is supplied in
328022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 native form.
329022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Interface              The interface for the protocol being added
330022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Notify                 indicates whether notify the notification list
331022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 for this protocol
332022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
333022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  Invalid parameter
334022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_OUT_OF_RESOURCES   No enough buffer to allocate
335162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @retval EFI_SUCCESS            Protocol interface successfully installed
336162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
337162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
33828a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
33928a00297189c323096aae8e2975de94e8549613cyshangCoreInstallProtocolInterfaceNotify (
34028a00297189c323096aae8e2975de94e8549613cyshang  IN OUT EFI_HANDLE     *UserHandle,
34128a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_GUID           *Protocol,
34228a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_INTERFACE_TYPE InterfaceType,
34328a00297189c323096aae8e2975de94e8549613cyshang  IN VOID               *Interface,
34428a00297189c323096aae8e2975de94e8549613cyshang  IN BOOLEAN            Notify
34528a00297189c323096aae8e2975de94e8549613cyshang  )
34628a00297189c323096aae8e2975de94e8549613cyshang{
34728a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE  *Prot;
34828a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_ENTRY      *ProtEntry;
34928a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE             *Handle;
35028a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS          Status;
35128a00297189c323096aae8e2975de94e8549613cyshang  VOID                *ExistingInterface;
35228a00297189c323096aae8e2975de94e8549613cyshang
35328a00297189c323096aae8e2975de94e8549613cyshang  //
35428a00297189c323096aae8e2975de94e8549613cyshang  // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
35528a00297189c323096aae8e2975de94e8549613cyshang  // Also added check for invalid UserHandle and Protocol pointers.
35628a00297189c323096aae8e2975de94e8549613cyshang  //
35728a00297189c323096aae8e2975de94e8549613cyshang  if (UserHandle == NULL || Protocol == NULL) {
35828a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
35928a00297189c323096aae8e2975de94e8549613cyshang  }
36028a00297189c323096aae8e2975de94e8549613cyshang
36128a00297189c323096aae8e2975de94e8549613cyshang  if (InterfaceType != EFI_NATIVE_INTERFACE) {
36228a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
36328a00297189c323096aae8e2975de94e8549613cyshang  }
36428a00297189c323096aae8e2975de94e8549613cyshang
36528a00297189c323096aae8e2975de94e8549613cyshang  //
36628a00297189c323096aae8e2975de94e8549613cyshang  // Print debug message
36728a00297189c323096aae8e2975de94e8549613cyshang  //
36858125fb3f9dda7f15a540b16595dc24dab0dd423qhuang  DEBUG((DEBUG_INFO, "InstallProtocolInterface: %g %p\n", Protocol, Interface));
36928a00297189c323096aae8e2975de94e8549613cyshang
37028a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_OUT_OF_RESOURCES;
37128a00297189c323096aae8e2975de94e8549613cyshang  Prot = NULL;
37228a00297189c323096aae8e2975de94e8549613cyshang  Handle = NULL;
37328a00297189c323096aae8e2975de94e8549613cyshang
3744008328a99b99770764d1988e9fb2e12ce57e9f3qwang  if (*UserHandle != NULL) {
37528a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
37628a00297189c323096aae8e2975de94e8549613cyshang    if (!EFI_ERROR (Status)) {
37728a00297189c323096aae8e2975de94e8549613cyshang      return EFI_INVALID_PARAMETER;
37828a00297189c323096aae8e2975de94e8549613cyshang    }
37928a00297189c323096aae8e2975de94e8549613cyshang  }
38028a00297189c323096aae8e2975de94e8549613cyshang
38128a00297189c323096aae8e2975de94e8549613cyshang  //
382022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  // Lock the protocol database
38328a00297189c323096aae8e2975de94e8549613cyshang  //
38428a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
38528a00297189c323096aae8e2975de94e8549613cyshang
38628a00297189c323096aae8e2975de94e8549613cyshang  //
38728a00297189c323096aae8e2975de94e8549613cyshang  // Lookup the Protocol Entry for the requested protocol
38828a00297189c323096aae8e2975de94e8549613cyshang  //
38928a00297189c323096aae8e2975de94e8549613cyshang  ProtEntry = CoreFindProtocolEntry (Protocol, TRUE);
39028a00297189c323096aae8e2975de94e8549613cyshang  if (ProtEntry == NULL) {
39128a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
39228a00297189c323096aae8e2975de94e8549613cyshang  }
39328a00297189c323096aae8e2975de94e8549613cyshang
39428a00297189c323096aae8e2975de94e8549613cyshang  //
39528a00297189c323096aae8e2975de94e8549613cyshang  // Allocate a new protocol interface structure
39628a00297189c323096aae8e2975de94e8549613cyshang  //
3979c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang  Prot = AllocateZeroPool (sizeof(PROTOCOL_INTERFACE));
39828a00297189c323096aae8e2975de94e8549613cyshang  if (Prot == NULL) {
39928a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_OUT_OF_RESOURCES;
40028a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
40128a00297189c323096aae8e2975de94e8549613cyshang  }
40228a00297189c323096aae8e2975de94e8549613cyshang
40328a00297189c323096aae8e2975de94e8549613cyshang  //
40428a00297189c323096aae8e2975de94e8549613cyshang  // If caller didn't supply a handle, allocate a new one
40528a00297189c323096aae8e2975de94e8549613cyshang  //
40628a00297189c323096aae8e2975de94e8549613cyshang  Handle = (IHANDLE *)*UserHandle;
40728a00297189c323096aae8e2975de94e8549613cyshang  if (Handle == NULL) {
4089c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang    Handle = AllocateZeroPool (sizeof(IHANDLE));
40928a00297189c323096aae8e2975de94e8549613cyshang    if (Handle == NULL) {
41028a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_OUT_OF_RESOURCES;
41128a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
41228a00297189c323096aae8e2975de94e8549613cyshang    }
41328a00297189c323096aae8e2975de94e8549613cyshang
41428a00297189c323096aae8e2975de94e8549613cyshang    //
41528a00297189c323096aae8e2975de94e8549613cyshang    // Initialize new handler structure
41628a00297189c323096aae8e2975de94e8549613cyshang    //
41728a00297189c323096aae8e2975de94e8549613cyshang    Handle->Signature = EFI_HANDLE_SIGNATURE;
41828a00297189c323096aae8e2975de94e8549613cyshang    InitializeListHead (&Handle->Protocols);
41928a00297189c323096aae8e2975de94e8549613cyshang
42028a00297189c323096aae8e2975de94e8549613cyshang    //
42128a00297189c323096aae8e2975de94e8549613cyshang    // Initialize the Key to show that the handle has been created/modified
42228a00297189c323096aae8e2975de94e8549613cyshang    //
42328a00297189c323096aae8e2975de94e8549613cyshang    gHandleDatabaseKey++;
42428a00297189c323096aae8e2975de94e8549613cyshang    Handle->Key = gHandleDatabaseKey;
42528a00297189c323096aae8e2975de94e8549613cyshang
42628a00297189c323096aae8e2975de94e8549613cyshang    //
42728a00297189c323096aae8e2975de94e8549613cyshang    // Add this handle to the list global list of all handles
42828a00297189c323096aae8e2975de94e8549613cyshang    // in the system
42928a00297189c323096aae8e2975de94e8549613cyshang    //
43028a00297189c323096aae8e2975de94e8549613cyshang    InsertTailList (&gHandleList, &Handle->AllHandles);
431022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  }
43228a00297189c323096aae8e2975de94e8549613cyshang
43328a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (Handle);
43428a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
43528a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
43628a00297189c323096aae8e2975de94e8549613cyshang  }
43728a00297189c323096aae8e2975de94e8549613cyshang
43828a00297189c323096aae8e2975de94e8549613cyshang  //
43928a00297189c323096aae8e2975de94e8549613cyshang  // Each interface that is added must be unique
44028a00297189c323096aae8e2975de94e8549613cyshang  //
44128a00297189c323096aae8e2975de94e8549613cyshang  ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL);
44228a00297189c323096aae8e2975de94e8549613cyshang
44328a00297189c323096aae8e2975de94e8549613cyshang  //
44428a00297189c323096aae8e2975de94e8549613cyshang  // Initialize the protocol interface structure
44528a00297189c323096aae8e2975de94e8549613cyshang  //
44628a00297189c323096aae8e2975de94e8549613cyshang  Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
44728a00297189c323096aae8e2975de94e8549613cyshang  Prot->Handle = Handle;
44828a00297189c323096aae8e2975de94e8549613cyshang  Prot->Protocol = ProtEntry;
44928a00297189c323096aae8e2975de94e8549613cyshang  Prot->Interface = Interface;
45028a00297189c323096aae8e2975de94e8549613cyshang
45128a00297189c323096aae8e2975de94e8549613cyshang  //
45228a00297189c323096aae8e2975de94e8549613cyshang  // Initalize OpenProtocol Data base
45328a00297189c323096aae8e2975de94e8549613cyshang  //
45428a00297189c323096aae8e2975de94e8549613cyshang  InitializeListHead (&Prot->OpenList);
45528a00297189c323096aae8e2975de94e8549613cyshang  Prot->OpenListCount = 0;
45628a00297189c323096aae8e2975de94e8549613cyshang
45728a00297189c323096aae8e2975de94e8549613cyshang  //
458022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  // Add this protocol interface to the head of the supported
45928a00297189c323096aae8e2975de94e8549613cyshang  // protocol list for this handle
46028a00297189c323096aae8e2975de94e8549613cyshang  //
46128a00297189c323096aae8e2975de94e8549613cyshang  InsertHeadList (&Handle->Protocols, &Prot->Link);
46228a00297189c323096aae8e2975de94e8549613cyshang
46328a00297189c323096aae8e2975de94e8549613cyshang  //
464022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  // Add this protocol interface to the tail of the
46528a00297189c323096aae8e2975de94e8549613cyshang  // protocol entry
466022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  //
46728a00297189c323096aae8e2975de94e8549613cyshang  InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
46828a00297189c323096aae8e2975de94e8549613cyshang
46928a00297189c323096aae8e2975de94e8549613cyshang  //
470022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  // Notify the notification list for this protocol
47128a00297189c323096aae8e2975de94e8549613cyshang  //
47228a00297189c323096aae8e2975de94e8549613cyshang  if (Notify) {
47328a00297189c323096aae8e2975de94e8549613cyshang    CoreNotifyProtocolEntry (ProtEntry);
47428a00297189c323096aae8e2975de94e8549613cyshang  }
47528a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_SUCCESS;
47628a00297189c323096aae8e2975de94e8549613cyshang
47728a00297189c323096aae8e2975de94e8549613cyshangDone:
47828a00297189c323096aae8e2975de94e8549613cyshang  //
47928a00297189c323096aae8e2975de94e8549613cyshang  // Done, unlock the database and return
48028a00297189c323096aae8e2975de94e8549613cyshang  //
48128a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
48228a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status)) {
48328a00297189c323096aae8e2975de94e8549613cyshang    //
48428a00297189c323096aae8e2975de94e8549613cyshang    // Return the new handle back to the caller
48528a00297189c323096aae8e2975de94e8549613cyshang    //
48628a00297189c323096aae8e2975de94e8549613cyshang    *UserHandle = Handle;
48728a00297189c323096aae8e2975de94e8549613cyshang  } else {
48828a00297189c323096aae8e2975de94e8549613cyshang    //
48928a00297189c323096aae8e2975de94e8549613cyshang    // There was an error, clean up
49028a00297189c323096aae8e2975de94e8549613cyshang    //
49128a00297189c323096aae8e2975de94e8549613cyshang    if (Prot != NULL) {
49228a00297189c323096aae8e2975de94e8549613cyshang      CoreFreePool (Prot);
49328a00297189c323096aae8e2975de94e8549613cyshang    }
49428a00297189c323096aae8e2975de94e8549613cyshang  }
49528a00297189c323096aae8e2975de94e8549613cyshang
49628a00297189c323096aae8e2975de94e8549613cyshang  return Status;
49728a00297189c323096aae8e2975de94e8549613cyshang}
49828a00297189c323096aae8e2975de94e8549613cyshang
49928a00297189c323096aae8e2975de94e8549613cyshang
50028a00297189c323096aae8e2975de94e8549613cyshang
50128a00297189c323096aae8e2975de94e8549613cyshang
502162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
50328a00297189c323096aae8e2975de94e8549613cyshang  Installs a list of protocol interface into the boot services environment.
50428a00297189c323096aae8e2975de94e8549613cyshang  This function calls InstallProtocolInterface() in a loop. If any error
505162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  occures all the protocols added by this function are removed. This is
50628a00297189c323096aae8e2975de94e8549613cyshang  basically a lib function to save space.
50728a00297189c323096aae8e2975de94e8549613cyshang
5084a23eaa9e0400325624e7d45b4a0e1e39c431d30niruiyu  @param  Handle                 The pointer to a handle to install the new
5094a23eaa9e0400325624e7d45b4a0e1e39c431d30niruiyu                                 protocol interfaces on, or a pointer to NULL
5104a23eaa9e0400325624e7d45b4a0e1e39c431d30niruiyu                                 if a new handle is to be allocated.
511022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ...                    EFI_GUID followed by protocol instance. A NULL
512022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 terminates the  list. The pairs are the
513022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 arguments to InstallProtocolInterface(). All the
514022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 protocols are added to Handle.
51528a00297189c323096aae8e2975de94e8549613cyshang
5165a7b9bbe08a5dfc8de6f5091a4b140818604d403Shumin Qiu  @retval EFI_SUCCESS            All the protocol interface was installed.
5175a7b9bbe08a5dfc8de6f5091a4b140818604d403Shumin Qiu  @retval EFI_OUT_OF_RESOURCES   There was not enough memory in pool to install all the protocols.
5185a7b9bbe08a5dfc8de6f5091a4b140818604d403Shumin Qiu  @retval EFI_ALREADY_STARTED    A Device Path Protocol instance was passed in that is already present in
5195a7b9bbe08a5dfc8de6f5091a4b140818604d403Shumin Qiu                                 the handle database.
520022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  Handle is NULL.
5215a7b9bbe08a5dfc8de6f5091a4b140818604d403Shumin Qiu  @retval EFI_INVALID_PARAMETER  Protocol is already installed on the handle specified by Handle.
52228a00297189c323096aae8e2975de94e8549613cyshang
523162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
524162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFI_STATUS
525162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFIAPI
526162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreInstallMultipleProtocolInterfaces (
527162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN OUT EFI_HANDLE           *Handle,
528162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  ...
529162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
53028a00297189c323096aae8e2975de94e8549613cyshang{
531162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  VA_LIST                   Args;
53228a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                Status;
53328a00297189c323096aae8e2975de94e8549613cyshang  EFI_GUID                  *Protocol;
53428a00297189c323096aae8e2975de94e8549613cyshang  VOID                      *Interface;
53528a00297189c323096aae8e2975de94e8549613cyshang  EFI_TPL                   OldTpl;
53628a00297189c323096aae8e2975de94e8549613cyshang  UINTN                     Index;
53728a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                OldHandle;
53828a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE                DeviceHandle;
53928a00297189c323096aae8e2975de94e8549613cyshang  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
540022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
54128a00297189c323096aae8e2975de94e8549613cyshang  if (Handle == NULL) {
54228a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
54328a00297189c323096aae8e2975de94e8549613cyshang  }
544022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
545022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  //
546022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  // Syncronize with notifcations.
54728a00297189c323096aae8e2975de94e8549613cyshang  //
54828a00297189c323096aae8e2975de94e8549613cyshang  OldTpl = CoreRaiseTpl (TPL_NOTIFY);
54928a00297189c323096aae8e2975de94e8549613cyshang  OldHandle = *Handle;
55028a00297189c323096aae8e2975de94e8549613cyshang
55128a00297189c323096aae8e2975de94e8549613cyshang  //
55228a00297189c323096aae8e2975de94e8549613cyshang  // Check for duplicate device path and install the protocol interfaces
55328a00297189c323096aae8e2975de94e8549613cyshang  //
554162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  VA_START (Args, Handle);
55528a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
55628a00297189c323096aae8e2975de94e8549613cyshang    //
55728a00297189c323096aae8e2975de94e8549613cyshang    // If protocol is NULL, then it's the end of the list
55828a00297189c323096aae8e2975de94e8549613cyshang    //
559162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang    Protocol = VA_ARG (Args, EFI_GUID *);
56028a00297189c323096aae8e2975de94e8549613cyshang    if (Protocol == NULL) {
56128a00297189c323096aae8e2975de94e8549613cyshang      break;
56228a00297189c323096aae8e2975de94e8549613cyshang    }
56328a00297189c323096aae8e2975de94e8549613cyshang
564162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang    Interface = VA_ARG (Args, VOID *);
56528a00297189c323096aae8e2975de94e8549613cyshang
56628a00297189c323096aae8e2975de94e8549613cyshang    //
56728a00297189c323096aae8e2975de94e8549613cyshang    // Make sure you are installing on top a device path that has already been added.
56828a00297189c323096aae8e2975de94e8549613cyshang    //
56928a00297189c323096aae8e2975de94e8549613cyshang    if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) {
57028a00297189c323096aae8e2975de94e8549613cyshang      DeviceHandle = NULL;
57128a00297189c323096aae8e2975de94e8549613cyshang      DevicePath   = Interface;
57228a00297189c323096aae8e2975de94e8549613cyshang      Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle);
5734008328a99b99770764d1988e9fb2e12ce57e9f3qwang      if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(DevicePath)) {
57428a00297189c323096aae8e2975de94e8549613cyshang        Status = EFI_ALREADY_STARTED;
57528a00297189c323096aae8e2975de94e8549613cyshang        continue;
57628a00297189c323096aae8e2975de94e8549613cyshang      }
57728a00297189c323096aae8e2975de94e8549613cyshang    }
578022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
57928a00297189c323096aae8e2975de94e8549613cyshang    //
58028a00297189c323096aae8e2975de94e8549613cyshang    // Install it
58128a00297189c323096aae8e2975de94e8549613cyshang    //
58228a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
58328a00297189c323096aae8e2975de94e8549613cyshang  }
584a70c0fd846dc339135c0b5607983d20d891dc149qwang  VA_END (Args);
585022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
58628a00297189c323096aae8e2975de94e8549613cyshang  //
58728a00297189c323096aae8e2975de94e8549613cyshang  // If there was an error, remove all the interfaces that were installed without any errors
58828a00297189c323096aae8e2975de94e8549613cyshang  //
58928a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
59028a00297189c323096aae8e2975de94e8549613cyshang    //
59128a00297189c323096aae8e2975de94e8549613cyshang    // Reset the va_arg back to the first argument.
59228a00297189c323096aae8e2975de94e8549613cyshang    //
593162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang    VA_START (Args, Handle);
59428a00297189c323096aae8e2975de94e8549613cyshang    for (; Index > 1; Index--) {
595162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang      Protocol = VA_ARG (Args, EFI_GUID *);
596162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang      Interface = VA_ARG (Args, VOID *);
59728a00297189c323096aae8e2975de94e8549613cyshang      CoreUninstallProtocolInterface (*Handle, Protocol, Interface);
598022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang    }
599a70c0fd846dc339135c0b5607983d20d891dc149qwang    VA_END (Args);
600a70c0fd846dc339135c0b5607983d20d891dc149qwang
60128a00297189c323096aae8e2975de94e8549613cyshang    *Handle = OldHandle;
60228a00297189c323096aae8e2975de94e8549613cyshang  }
60328a00297189c323096aae8e2975de94e8549613cyshang
60428a00297189c323096aae8e2975de94e8549613cyshang  //
60528a00297189c323096aae8e2975de94e8549613cyshang  // Done
60628a00297189c323096aae8e2975de94e8549613cyshang  //
60728a00297189c323096aae8e2975de94e8549613cyshang  CoreRestoreTpl (OldTpl);
60828a00297189c323096aae8e2975de94e8549613cyshang  return Status;
60928a00297189c323096aae8e2975de94e8549613cyshang}
61028a00297189c323096aae8e2975de94e8549613cyshang
61128a00297189c323096aae8e2975de94e8549613cyshang
612162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
61328a00297189c323096aae8e2975de94e8549613cyshang  Attempts to disconnect all drivers that are using the protocol interface being queried.
61428a00297189c323096aae8e2975de94e8549613cyshang  If failed, reconnect all drivers disconnected.
615162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Note: This function doesn't do parameters checking, it's caller's responsibility
616162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  to pass in valid parameters.
61728a00297189c323096aae8e2975de94e8549613cyshang
618022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle on which the protocol is installed
619022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Prot                   The protocol to disconnect drivers from
62028a00297189c323096aae8e2975de94e8549613cyshang
621022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS            Drivers using the protocol interface are all
622022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 disconnected
623162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @retval EFI_ACCESS_DENIED      Failed to disconnect one or all of the drivers
62428a00297189c323096aae8e2975de94e8549613cyshang
625162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
626162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangEFI_STATUS
627162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreDisconnectControllersUsingProtocolInterface (
628162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN EFI_HANDLE           UserHandle,
629162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  IN PROTOCOL_INTERFACE   *Prot
630162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
63128a00297189c323096aae8e2975de94e8549613cyshang{
63228a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS            Status;
63328a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN               ItemFound;
63428a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY            *Link;
63528a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA    *OpenData;
63628a00297189c323096aae8e2975de94e8549613cyshang
63728a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_SUCCESS;
638022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
63928a00297189c323096aae8e2975de94e8549613cyshang  //
64028a00297189c323096aae8e2975de94e8549613cyshang  // Attempt to disconnect all drivers from this protocol interface
64128a00297189c323096aae8e2975de94e8549613cyshang  //
64228a00297189c323096aae8e2975de94e8549613cyshang  do {
64328a00297189c323096aae8e2975de94e8549613cyshang    ItemFound = FALSE;
64428a00297189c323096aae8e2975de94e8549613cyshang    for ( Link = Prot->OpenList.ForwardLink;
64528a00297189c323096aae8e2975de94e8549613cyshang          (Link != &Prot->OpenList) && !ItemFound;
64628a00297189c323096aae8e2975de94e8549613cyshang          Link = Link->ForwardLink ) {
64728a00297189c323096aae8e2975de94e8549613cyshang      OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
6486e53646837da984d2f5dd64467ba7a8943b459aeqhuang      if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
64928a00297189c323096aae8e2975de94e8549613cyshang        ItemFound = TRUE;
65028a00297189c323096aae8e2975de94e8549613cyshang        CoreReleaseProtocolLock ();
65128a00297189c323096aae8e2975de94e8549613cyshang        Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
65228a00297189c323096aae8e2975de94e8549613cyshang        CoreAcquireProtocolLock ();
65328a00297189c323096aae8e2975de94e8549613cyshang        if (EFI_ERROR (Status)) {
65428a00297189c323096aae8e2975de94e8549613cyshang           ItemFound = FALSE;
65528a00297189c323096aae8e2975de94e8549613cyshang           break;
65628a00297189c323096aae8e2975de94e8549613cyshang        }
65728a00297189c323096aae8e2975de94e8549613cyshang      }
65828a00297189c323096aae8e2975de94e8549613cyshang    }
65928a00297189c323096aae8e2975de94e8549613cyshang  } while (ItemFound);
66028a00297189c323096aae8e2975de94e8549613cyshang
66128a00297189c323096aae8e2975de94e8549613cyshang  if (!EFI_ERROR (Status)) {
66228a00297189c323096aae8e2975de94e8549613cyshang    //
66328a00297189c323096aae8e2975de94e8549613cyshang    // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items
66428a00297189c323096aae8e2975de94e8549613cyshang    //
66528a00297189c323096aae8e2975de94e8549613cyshang    do {
66628a00297189c323096aae8e2975de94e8549613cyshang      ItemFound = FALSE;
66728a00297189c323096aae8e2975de94e8549613cyshang      for ( Link = Prot->OpenList.ForwardLink;
66828a00297189c323096aae8e2975de94e8549613cyshang            (Link != &Prot->OpenList) && !ItemFound;
66928a00297189c323096aae8e2975de94e8549613cyshang            Link = Link->ForwardLink ) {
67028a00297189c323096aae8e2975de94e8549613cyshang        OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
6716e53646837da984d2f5dd64467ba7a8943b459aeqhuang        if ((OpenData->Attributes &
6726e53646837da984d2f5dd64467ba7a8943b459aeqhuang            (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0) {
67328a00297189c323096aae8e2975de94e8549613cyshang          ItemFound = TRUE;
674022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          RemoveEntryList (&OpenData->Link);
67528a00297189c323096aae8e2975de94e8549613cyshang          Prot->OpenListCount--;
67628a00297189c323096aae8e2975de94e8549613cyshang          CoreFreePool (OpenData);
67728a00297189c323096aae8e2975de94e8549613cyshang        }
67828a00297189c323096aae8e2975de94e8549613cyshang      }
67928a00297189c323096aae8e2975de94e8549613cyshang    } while (ItemFound);
68028a00297189c323096aae8e2975de94e8549613cyshang  }
68128a00297189c323096aae8e2975de94e8549613cyshang
68228a00297189c323096aae8e2975de94e8549613cyshang  //
68328a00297189c323096aae8e2975de94e8549613cyshang  // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
68428a00297189c323096aae8e2975de94e8549613cyshang  //
68528a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
68628a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
68728a00297189c323096aae8e2975de94e8549613cyshang    CoreConnectController (UserHandle, NULL, NULL, TRUE);
68828a00297189c323096aae8e2975de94e8549613cyshang    CoreAcquireProtocolLock ();
68928a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_ACCESS_DENIED;
69028a00297189c323096aae8e2975de94e8549613cyshang  }
69128a00297189c323096aae8e2975de94e8549613cyshang
69228a00297189c323096aae8e2975de94e8549613cyshang  return Status;
69328a00297189c323096aae8e2975de94e8549613cyshang}
69428a00297189c323096aae8e2975de94e8549613cyshang
69528a00297189c323096aae8e2975de94e8549613cyshang
696162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
697162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
698162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Uninstalls all instances of a protocol:interfacer from a handle.
699162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  If the last protocol interface is remove from the handle, the
700162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  handle is freed.
701162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
702022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle to remove the protocol handler from
703022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The protocol, of protocol:interface, to remove
704022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Interface              The interface, of protocol:interface, to remove
705162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
706022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
707162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @retval EFI_SUCCESS            Protocol interface successfully uninstalled.
708162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
709162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
71028a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
71128a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
71228a00297189c323096aae8e2975de94e8549613cyshangCoreUninstallProtocolInterface (
71328a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_HANDLE       UserHandle,
71428a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_GUID         *Protocol,
71528a00297189c323096aae8e2975de94e8549613cyshang  IN VOID             *Interface
71628a00297189c323096aae8e2975de94e8549613cyshang  )
71728a00297189c323096aae8e2975de94e8549613cyshang{
71828a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS            Status;
71928a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE               *Handle;
72028a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE    *Prot;
72128a00297189c323096aae8e2975de94e8549613cyshang
72228a00297189c323096aae8e2975de94e8549613cyshang  //
72328a00297189c323096aae8e2975de94e8549613cyshang  // Check that Protocol is valid
72428a00297189c323096aae8e2975de94e8549613cyshang  //
72528a00297189c323096aae8e2975de94e8549613cyshang  if (Protocol == NULL) {
72628a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
72728a00297189c323096aae8e2975de94e8549613cyshang  }
72828a00297189c323096aae8e2975de94e8549613cyshang
72928a00297189c323096aae8e2975de94e8549613cyshang  //
73028a00297189c323096aae8e2975de94e8549613cyshang  // Check that UserHandle is a valid handle
73128a00297189c323096aae8e2975de94e8549613cyshang  //
73228a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (UserHandle);
73328a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
73428a00297189c323096aae8e2975de94e8549613cyshang    return Status;
73528a00297189c323096aae8e2975de94e8549613cyshang  }
73628a00297189c323096aae8e2975de94e8549613cyshang
73728a00297189c323096aae8e2975de94e8549613cyshang  //
73828a00297189c323096aae8e2975de94e8549613cyshang  // Lock the protocol database
73928a00297189c323096aae8e2975de94e8549613cyshang  //
74028a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
74128a00297189c323096aae8e2975de94e8549613cyshang
74228a00297189c323096aae8e2975de94e8549613cyshang  //
74328a00297189c323096aae8e2975de94e8549613cyshang  // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
74428a00297189c323096aae8e2975de94e8549613cyshang  //
74528a00297189c323096aae8e2975de94e8549613cyshang  Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface);
74628a00297189c323096aae8e2975de94e8549613cyshang  if (Prot == NULL) {
74728a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_NOT_FOUND;
74828a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
74928a00297189c323096aae8e2975de94e8549613cyshang  }
75028a00297189c323096aae8e2975de94e8549613cyshang
75128a00297189c323096aae8e2975de94e8549613cyshang  //
75228a00297189c323096aae8e2975de94e8549613cyshang  // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
75328a00297189c323096aae8e2975de94e8549613cyshang  //
75428a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreDisconnectControllersUsingProtocolInterface (
75528a00297189c323096aae8e2975de94e8549613cyshang             UserHandle,
75628a00297189c323096aae8e2975de94e8549613cyshang             Prot
75728a00297189c323096aae8e2975de94e8549613cyshang             );
75828a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
75928a00297189c323096aae8e2975de94e8549613cyshang    //
76028a00297189c323096aae8e2975de94e8549613cyshang    // One or more drivers refused to release, so return the error
76128a00297189c323096aae8e2975de94e8549613cyshang    //
76228a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
76328a00297189c323096aae8e2975de94e8549613cyshang  }
76428a00297189c323096aae8e2975de94e8549613cyshang
76528a00297189c323096aae8e2975de94e8549613cyshang  //
76628a00297189c323096aae8e2975de94e8549613cyshang  // Remove the protocol interface from the protocol
76728a00297189c323096aae8e2975de94e8549613cyshang  //
76828a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_NOT_FOUND;
76928a00297189c323096aae8e2975de94e8549613cyshang  Handle = (IHANDLE *)UserHandle;
77028a00297189c323096aae8e2975de94e8549613cyshang  Prot   = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
77128a00297189c323096aae8e2975de94e8549613cyshang
77228a00297189c323096aae8e2975de94e8549613cyshang  if (Prot != NULL) {
77328a00297189c323096aae8e2975de94e8549613cyshang    //
77428a00297189c323096aae8e2975de94e8549613cyshang    // Update the Key to show that the handle has been created/modified
77528a00297189c323096aae8e2975de94e8549613cyshang    //
77628a00297189c323096aae8e2975de94e8549613cyshang    gHandleDatabaseKey++;
77728a00297189c323096aae8e2975de94e8549613cyshang    Handle->Key = gHandleDatabaseKey;
778022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
77928a00297189c323096aae8e2975de94e8549613cyshang    //
78028a00297189c323096aae8e2975de94e8549613cyshang    // Remove the protocol interface from the handle
78128a00297189c323096aae8e2975de94e8549613cyshang    //
78228a00297189c323096aae8e2975de94e8549613cyshang    RemoveEntryList (&Prot->Link);
78328a00297189c323096aae8e2975de94e8549613cyshang
78428a00297189c323096aae8e2975de94e8549613cyshang    //
78528a00297189c323096aae8e2975de94e8549613cyshang    // Free the memory
78628a00297189c323096aae8e2975de94e8549613cyshang    //
78728a00297189c323096aae8e2975de94e8549613cyshang    Prot->Signature = 0;
78828a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (Prot);
78928a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_SUCCESS;
79028a00297189c323096aae8e2975de94e8549613cyshang  }
79128a00297189c323096aae8e2975de94e8549613cyshang
79228a00297189c323096aae8e2975de94e8549613cyshang  //
79328a00297189c323096aae8e2975de94e8549613cyshang  // If there are no more handlers for the handle, free the handle
79428a00297189c323096aae8e2975de94e8549613cyshang  //
79528a00297189c323096aae8e2975de94e8549613cyshang  if (IsListEmpty (&Handle->Protocols)) {
79628a00297189c323096aae8e2975de94e8549613cyshang    Handle->Signature = 0;
79728a00297189c323096aae8e2975de94e8549613cyshang    RemoveEntryList (&Handle->AllHandles);
79828a00297189c323096aae8e2975de94e8549613cyshang    CoreFreePool (Handle);
79928a00297189c323096aae8e2975de94e8549613cyshang  }
80028a00297189c323096aae8e2975de94e8549613cyshang
801022c6d45ef78605c173023f53984e4dfaf7b11f4qhuangDone:
80228a00297189c323096aae8e2975de94e8549613cyshang  //
80328a00297189c323096aae8e2975de94e8549613cyshang  // Done, unlock the database and return
80428a00297189c323096aae8e2975de94e8549613cyshang  //
80528a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
80628a00297189c323096aae8e2975de94e8549613cyshang  return Status;
80728a00297189c323096aae8e2975de94e8549613cyshang}
80828a00297189c323096aae8e2975de94e8549613cyshang
80928a00297189c323096aae8e2975de94e8549613cyshang
81028a00297189c323096aae8e2975de94e8549613cyshang
811162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
812162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
813162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Uninstalls a list of protocol interface in the boot services environment.
814162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  This function calls UnisatllProtocolInterface() in a loop. This is
815162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  basically a lib function to save space.
816162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
817022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Handle                 The handle to uninstall the protocol
818022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ...                    EFI_GUID followed by protocol instance. A NULL
819022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 terminates the  list. The pairs are the
820022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 arguments to UninstallProtocolInterface(). All
821022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 the protocols are added to Handle.
822162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
823162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return Status code
824162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
825162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
82628a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
82728a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
82828a00297189c323096aae8e2975de94e8549613cyshangCoreUninstallMultipleProtocolInterfaces (
82928a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_HANDLE           Handle,
83028a00297189c323096aae8e2975de94e8549613cyshang  ...
83128a00297189c323096aae8e2975de94e8549613cyshang  )
83228a00297189c323096aae8e2975de94e8549613cyshang{
83328a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS      Status;
834162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  VA_LIST         Args;
83528a00297189c323096aae8e2975de94e8549613cyshang  EFI_GUID        *Protocol;
83628a00297189c323096aae8e2975de94e8549613cyshang  VOID            *Interface;
83728a00297189c323096aae8e2975de94e8549613cyshang  UINTN           Index;
83828a00297189c323096aae8e2975de94e8549613cyshang
839162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  VA_START (Args, Handle);
84028a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
84128a00297189c323096aae8e2975de94e8549613cyshang    //
84228a00297189c323096aae8e2975de94e8549613cyshang    // If protocol is NULL, then it's the end of the list
84328a00297189c323096aae8e2975de94e8549613cyshang    //
844162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang    Protocol = VA_ARG (Args, EFI_GUID *);
84528a00297189c323096aae8e2975de94e8549613cyshang    if (Protocol == NULL) {
84628a00297189c323096aae8e2975de94e8549613cyshang      break;
84728a00297189c323096aae8e2975de94e8549613cyshang    }
84828a00297189c323096aae8e2975de94e8549613cyshang
849162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang    Interface = VA_ARG (Args, VOID *);
85028a00297189c323096aae8e2975de94e8549613cyshang
85128a00297189c323096aae8e2975de94e8549613cyshang    //
85228a00297189c323096aae8e2975de94e8549613cyshang    // Uninstall it
85328a00297189c323096aae8e2975de94e8549613cyshang    //
85428a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface);
85528a00297189c323096aae8e2975de94e8549613cyshang  }
856a70c0fd846dc339135c0b5607983d20d891dc149qwang  VA_END (Args);
85728a00297189c323096aae8e2975de94e8549613cyshang
85828a00297189c323096aae8e2975de94e8549613cyshang  //
85928a00297189c323096aae8e2975de94e8549613cyshang  // If there was an error, add all the interfaces that were
86028a00297189c323096aae8e2975de94e8549613cyshang  // uninstalled without any errors
86128a00297189c323096aae8e2975de94e8549613cyshang  //
86228a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
86328a00297189c323096aae8e2975de94e8549613cyshang    //
86428a00297189c323096aae8e2975de94e8549613cyshang    // Reset the va_arg back to the first argument.
86528a00297189c323096aae8e2975de94e8549613cyshang    //
866162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang    VA_START (Args, Handle);
86728a00297189c323096aae8e2975de94e8549613cyshang    for (; Index > 1; Index--) {
868162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang      Protocol = VA_ARG(Args, EFI_GUID *);
869162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang      Interface = VA_ARG(Args, VOID *);
87028a00297189c323096aae8e2975de94e8549613cyshang      CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
871022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang    }
872a70c0fd846dc339135c0b5607983d20d891dc149qwang    VA_END (Args);
87328a00297189c323096aae8e2975de94e8549613cyshang  }
87428a00297189c323096aae8e2975de94e8549613cyshang
87528a00297189c323096aae8e2975de94e8549613cyshang  return Status;
876022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang}
87728a00297189c323096aae8e2975de94e8549613cyshang
878162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
879162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
880162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Locate a certain GUID protocol interface in a Handle's protocols.
881162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
882022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle to obtain the protocol interface on
883022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The GUID of the protocol
884162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
885162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return The requested protocol interface for the handle
886162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
887162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
88828a00297189c323096aae8e2975de94e8549613cyshangPROTOCOL_INTERFACE  *
88928a00297189c323096aae8e2975de94e8549613cyshangCoreGetProtocolInterface (
89028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                UserHandle,
89128a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_GUID                  *Protocol
89228a00297189c323096aae8e2975de94e8549613cyshang  )
89328a00297189c323096aae8e2975de94e8549613cyshang{
89428a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS          Status;
89528a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_ENTRY      *ProtEntry;
89628a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE  *Prot;
89728a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE             *Handle;
89828a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY          *Link;
89928a00297189c323096aae8e2975de94e8549613cyshang
90028a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (UserHandle);
90128a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
90228a00297189c323096aae8e2975de94e8549613cyshang    return NULL;
90328a00297189c323096aae8e2975de94e8549613cyshang  }
904022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
90528a00297189c323096aae8e2975de94e8549613cyshang  Handle = (IHANDLE *)UserHandle;
90628a00297189c323096aae8e2975de94e8549613cyshang
90728a00297189c323096aae8e2975de94e8549613cyshang  //
90828a00297189c323096aae8e2975de94e8549613cyshang  // Look at each protocol interface for a match
90928a00297189c323096aae8e2975de94e8549613cyshang  //
91028a00297189c323096aae8e2975de94e8549613cyshang  for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
91128a00297189c323096aae8e2975de94e8549613cyshang    Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
91228a00297189c323096aae8e2975de94e8549613cyshang    ProtEntry = Prot->Protocol;
91328a00297189c323096aae8e2975de94e8549613cyshang    if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
91428a00297189c323096aae8e2975de94e8549613cyshang      return Prot;
91528a00297189c323096aae8e2975de94e8549613cyshang    }
91628a00297189c323096aae8e2975de94e8549613cyshang  }
91728a00297189c323096aae8e2975de94e8549613cyshang  return NULL;
91828a00297189c323096aae8e2975de94e8549613cyshang}
91928a00297189c323096aae8e2975de94e8549613cyshang
92028a00297189c323096aae8e2975de94e8549613cyshang
921162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
922162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
923162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Queries a handle to determine if it supports a specified protocol.
924162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
925022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle being queried.
926022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The published unique identifier of the protocol.
927022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Interface              Supplies the address where a pointer to the
928022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 corresponding Protocol Interface is returned.
929162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
93011074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @retval EFI_SUCCESS            The interface information for the specified protocol was returned.
93111074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @retval EFI_UNSUPPORTED        The device does not support the specified protocol.
932284ee2e829ab2453293b7dc4539727ad6c047163niruiyu  @retval EFI_INVALID_PARAMETER  Handle is NULL..
93311074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
93411074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @retval EFI_INVALID_PARAMETER  Interface is NULL.
935162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
936162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
93728a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
93828a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
93928a00297189c323096aae8e2975de94e8549613cyshangCoreHandleProtocol (
94028a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_HANDLE       UserHandle,
94128a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_GUID         *Protocol,
94228a00297189c323096aae8e2975de94e8549613cyshang  OUT VOID            **Interface
94328a00297189c323096aae8e2975de94e8549613cyshang  )
94428a00297189c323096aae8e2975de94e8549613cyshang{
94528a00297189c323096aae8e2975de94e8549613cyshang  return CoreOpenProtocol (
946022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          UserHandle,
947022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          Protocol,
948022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          Interface,
949022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          gDxeCoreImageHandle,
950022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang          NULL,
95128a00297189c323096aae8e2975de94e8549613cyshang          EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
95228a00297189c323096aae8e2975de94e8549613cyshang          );
95328a00297189c323096aae8e2975de94e8549613cyshang}
95428a00297189c323096aae8e2975de94e8549613cyshang
95528a00297189c323096aae8e2975de94e8549613cyshang
956162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
957162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
958162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Locates the installed protocol handler for the handle, and
959162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  invokes it to obtain the protocol interface. Usage information
960162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  is registered in the protocol data base.
961162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
962022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle to obtain the protocol interface on
963022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The ID of the protocol
964022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Interface              The location to return the protocol interface
965022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ImageHandle            The handle of the Image that is opening the
966022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 protocol interface specified by Protocol and
967022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 Interface.
968022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ControllerHandle       The controller handle that is requiring this
969022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 interface.
970022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Attributes             The open mode of the protocol interface
971022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 specified by Handle and Protocol.
972022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
973022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  Protocol is NULL.
974162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @retval EFI_SUCCESS            Get the protocol interface.
975162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
976162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
97728a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
97828a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
97928a00297189c323096aae8e2975de94e8549613cyshangCoreOpenProtocol (
98028a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                UserHandle,
98128a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_GUID                  *Protocol,
98228a00297189c323096aae8e2975de94e8549613cyshang  OUT VOID                      **Interface OPTIONAL,
98328a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ImageHandle,
98428a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                ControllerHandle,
98528a00297189c323096aae8e2975de94e8549613cyshang  IN  UINT32                    Attributes
98628a00297189c323096aae8e2975de94e8549613cyshang  )
98728a00297189c323096aae8e2975de94e8549613cyshang{
98828a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS          Status;
98928a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE  *Prot;
99028a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY          *Link;
99128a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA  *OpenData;
99228a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN             ByDriver;
99328a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN             Exclusive;
99428a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN             Disconnect;
99528a00297189c323096aae8e2975de94e8549613cyshang  BOOLEAN             ExactMatch;
99628a00297189c323096aae8e2975de94e8549613cyshang
99728a00297189c323096aae8e2975de94e8549613cyshang  //
99828a00297189c323096aae8e2975de94e8549613cyshang  // Check for invalid Protocol
99928a00297189c323096aae8e2975de94e8549613cyshang  //
100028a00297189c323096aae8e2975de94e8549613cyshang  if (Protocol == NULL) {
100128a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
100228a00297189c323096aae8e2975de94e8549613cyshang  }
100328a00297189c323096aae8e2975de94e8549613cyshang
100428a00297189c323096aae8e2975de94e8549613cyshang  //
100528a00297189c323096aae8e2975de94e8549613cyshang  // Check for invalid Interface
100628a00297189c323096aae8e2975de94e8549613cyshang  //
100728a00297189c323096aae8e2975de94e8549613cyshang  if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
100828a00297189c323096aae8e2975de94e8549613cyshang    if (Interface == NULL) {
100928a00297189c323096aae8e2975de94e8549613cyshang      return EFI_INVALID_PARAMETER;
101028a00297189c323096aae8e2975de94e8549613cyshang    } else {
101128a00297189c323096aae8e2975de94e8549613cyshang      *Interface = NULL;
101228a00297189c323096aae8e2975de94e8549613cyshang    }
101328a00297189c323096aae8e2975de94e8549613cyshang  }
1014022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
101528a00297189c323096aae8e2975de94e8549613cyshang  //
101628a00297189c323096aae8e2975de94e8549613cyshang  // Check for invalid UserHandle
101728a00297189c323096aae8e2975de94e8549613cyshang  //
101828a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (UserHandle);
101928a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
102028a00297189c323096aae8e2975de94e8549613cyshang    return Status;
102128a00297189c323096aae8e2975de94e8549613cyshang  }
102228a00297189c323096aae8e2975de94e8549613cyshang
102328a00297189c323096aae8e2975de94e8549613cyshang  //
102428a00297189c323096aae8e2975de94e8549613cyshang  // Check for invalid Attributes
102528a00297189c323096aae8e2975de94e8549613cyshang  //
102628a00297189c323096aae8e2975de94e8549613cyshang  switch (Attributes) {
102728a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
102828a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ImageHandle);
102928a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
103028a00297189c323096aae8e2975de94e8549613cyshang      return Status;
103128a00297189c323096aae8e2975de94e8549613cyshang    }
103228a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ControllerHandle);
103328a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
103428a00297189c323096aae8e2975de94e8549613cyshang      return Status;
103528a00297189c323096aae8e2975de94e8549613cyshang    }
103628a00297189c323096aae8e2975de94e8549613cyshang    if (UserHandle == ControllerHandle) {
103728a00297189c323096aae8e2975de94e8549613cyshang      return EFI_INVALID_PARAMETER;
103828a00297189c323096aae8e2975de94e8549613cyshang    }
103928a00297189c323096aae8e2975de94e8549613cyshang    break;
104028a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_DRIVER :
104128a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
104228a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ImageHandle);
104328a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
104428a00297189c323096aae8e2975de94e8549613cyshang      return Status;
104528a00297189c323096aae8e2975de94e8549613cyshang    }
104628a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ControllerHandle);
104728a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
104828a00297189c323096aae8e2975de94e8549613cyshang      return Status;
104928a00297189c323096aae8e2975de94e8549613cyshang    }
105028a00297189c323096aae8e2975de94e8549613cyshang    break;
105128a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_EXCLUSIVE :
105228a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ImageHandle);
105328a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
105428a00297189c323096aae8e2975de94e8549613cyshang      return Status;
105528a00297189c323096aae8e2975de94e8549613cyshang    }
105628a00297189c323096aae8e2975de94e8549613cyshang    break;
105728a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
105828a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
105928a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
106028a00297189c323096aae8e2975de94e8549613cyshang    break;
106128a00297189c323096aae8e2975de94e8549613cyshang  default:
106228a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
106328a00297189c323096aae8e2975de94e8549613cyshang  }
106428a00297189c323096aae8e2975de94e8549613cyshang
106528a00297189c323096aae8e2975de94e8549613cyshang  //
106628a00297189c323096aae8e2975de94e8549613cyshang  // Lock the protocol database
106728a00297189c323096aae8e2975de94e8549613cyshang  //
106828a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
106928a00297189c323096aae8e2975de94e8549613cyshang
107028a00297189c323096aae8e2975de94e8549613cyshang  //
107128a00297189c323096aae8e2975de94e8549613cyshang  // Look at each protocol interface for a match
107228a00297189c323096aae8e2975de94e8549613cyshang  //
107328a00297189c323096aae8e2975de94e8549613cyshang  Prot = CoreGetProtocolInterface (UserHandle, Protocol);
107428a00297189c323096aae8e2975de94e8549613cyshang  if (Prot == NULL) {
107528a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_UNSUPPORTED;
107628a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
107728a00297189c323096aae8e2975de94e8549613cyshang  }
107828a00297189c323096aae8e2975de94e8549613cyshang
107928a00297189c323096aae8e2975de94e8549613cyshang  //
108028a00297189c323096aae8e2975de94e8549613cyshang  // This is the protocol interface entry for this protocol
1081022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  //
108228a00297189c323096aae8e2975de94e8549613cyshang  if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
108328a00297189c323096aae8e2975de94e8549613cyshang    *Interface = Prot->Interface;
108428a00297189c323096aae8e2975de94e8549613cyshang  }
108528a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_SUCCESS;
108628a00297189c323096aae8e2975de94e8549613cyshang
108728a00297189c323096aae8e2975de94e8549613cyshang  ByDriver        = FALSE;
108828a00297189c323096aae8e2975de94e8549613cyshang  Exclusive       = FALSE;
108928a00297189c323096aae8e2975de94e8549613cyshang  for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
109028a00297189c323096aae8e2975de94e8549613cyshang    OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1091022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang    ExactMatch =  (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
109228a00297189c323096aae8e2975de94e8549613cyshang                            (OpenData->Attributes == Attributes)  &&
109328a00297189c323096aae8e2975de94e8549613cyshang                            (OpenData->ControllerHandle == ControllerHandle));
10946e53646837da984d2f5dd64467ba7a8943b459aeqhuang    if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
109528a00297189c323096aae8e2975de94e8549613cyshang      ByDriver = TRUE;
109628a00297189c323096aae8e2975de94e8549613cyshang      if (ExactMatch) {
109728a00297189c323096aae8e2975de94e8549613cyshang        Status = EFI_ALREADY_STARTED;
109828a00297189c323096aae8e2975de94e8549613cyshang        goto Done;
109928a00297189c323096aae8e2975de94e8549613cyshang      }
110028a00297189c323096aae8e2975de94e8549613cyshang    }
11016e53646837da984d2f5dd64467ba7a8943b459aeqhuang    if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
110228a00297189c323096aae8e2975de94e8549613cyshang      Exclusive = TRUE;
110328a00297189c323096aae8e2975de94e8549613cyshang    } else if (ExactMatch) {
110428a00297189c323096aae8e2975de94e8549613cyshang      OpenData->OpenCount++;
110528a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_SUCCESS;
110628a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
110728a00297189c323096aae8e2975de94e8549613cyshang    }
110828a00297189c323096aae8e2975de94e8549613cyshang  }
110928a00297189c323096aae8e2975de94e8549613cyshang
111028a00297189c323096aae8e2975de94e8549613cyshang  //
111128a00297189c323096aae8e2975de94e8549613cyshang  // ByDriver  TRUE  -> A driver is managing (UserHandle, Protocol)
111228a00297189c323096aae8e2975de94e8549613cyshang  // ByDriver  FALSE -> There are no drivers managing (UserHandle, Protocol)
111328a00297189c323096aae8e2975de94e8549613cyshang  // Exclusive TRUE  -> Something has exclusive access to (UserHandle, Protocol)
111428a00297189c323096aae8e2975de94e8549613cyshang  // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
111528a00297189c323096aae8e2975de94e8549613cyshang  //
111628a00297189c323096aae8e2975de94e8549613cyshang
111728a00297189c323096aae8e2975de94e8549613cyshang  switch (Attributes) {
111828a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_DRIVER :
111928a00297189c323096aae8e2975de94e8549613cyshang    if (Exclusive || ByDriver) {
112028a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_ACCESS_DENIED;
112128a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
112228a00297189c323096aae8e2975de94e8549613cyshang    }
112328a00297189c323096aae8e2975de94e8549613cyshang    break;
112428a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE :
112528a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_EXCLUSIVE :
112628a00297189c323096aae8e2975de94e8549613cyshang    if (Exclusive) {
112728a00297189c323096aae8e2975de94e8549613cyshang      Status = EFI_ACCESS_DENIED;
112828a00297189c323096aae8e2975de94e8549613cyshang      goto Done;
112928a00297189c323096aae8e2975de94e8549613cyshang    }
113028a00297189c323096aae8e2975de94e8549613cyshang    if (ByDriver) {
113128a00297189c323096aae8e2975de94e8549613cyshang      do {
113228a00297189c323096aae8e2975de94e8549613cyshang        Disconnect = FALSE;
113328a00297189c323096aae8e2975de94e8549613cyshang        for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) {
113428a00297189c323096aae8e2975de94e8549613cyshang          OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
11356e53646837da984d2f5dd64467ba7a8943b459aeqhuang          if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
113628a00297189c323096aae8e2975de94e8549613cyshang            Disconnect = TRUE;
113728a00297189c323096aae8e2975de94e8549613cyshang            CoreReleaseProtocolLock ();
113828a00297189c323096aae8e2975de94e8549613cyshang            Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
113928a00297189c323096aae8e2975de94e8549613cyshang            CoreAcquireProtocolLock ();
114028a00297189c323096aae8e2975de94e8549613cyshang            if (EFI_ERROR (Status)) {
114128a00297189c323096aae8e2975de94e8549613cyshang              Status = EFI_ACCESS_DENIED;
114228a00297189c323096aae8e2975de94e8549613cyshang              goto Done;
114328a00297189c323096aae8e2975de94e8549613cyshang            }
114428a00297189c323096aae8e2975de94e8549613cyshang          }
114528a00297189c323096aae8e2975de94e8549613cyshang        }
114628a00297189c323096aae8e2975de94e8549613cyshang      } while (Disconnect);
1147022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang    }
114828a00297189c323096aae8e2975de94e8549613cyshang    break;
114928a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER :
115028a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL :
115128a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_GET_PROTOCOL :
115228a00297189c323096aae8e2975de94e8549613cyshang  case EFI_OPEN_PROTOCOL_TEST_PROTOCOL :
115328a00297189c323096aae8e2975de94e8549613cyshang    break;
115428a00297189c323096aae8e2975de94e8549613cyshang  }
115528a00297189c323096aae8e2975de94e8549613cyshang
115628a00297189c323096aae8e2975de94e8549613cyshang  if (ImageHandle == NULL) {
115728a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_SUCCESS;
115828a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
115928a00297189c323096aae8e2975de94e8549613cyshang  }
116028a00297189c323096aae8e2975de94e8549613cyshang  //
116128a00297189c323096aae8e2975de94e8549613cyshang  // Create new entry
116228a00297189c323096aae8e2975de94e8549613cyshang  //
11639c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang  OpenData = AllocatePool (sizeof(OPEN_PROTOCOL_DATA));
116428a00297189c323096aae8e2975de94e8549613cyshang  if (OpenData == NULL) {
116528a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_OUT_OF_RESOURCES;
116628a00297189c323096aae8e2975de94e8549613cyshang  } else {
116728a00297189c323096aae8e2975de94e8549613cyshang    OpenData->Signature         = OPEN_PROTOCOL_DATA_SIGNATURE;
116828a00297189c323096aae8e2975de94e8549613cyshang    OpenData->AgentHandle       = ImageHandle;
116928a00297189c323096aae8e2975de94e8549613cyshang    OpenData->ControllerHandle  = ControllerHandle;
117028a00297189c323096aae8e2975de94e8549613cyshang    OpenData->Attributes        = Attributes;
117128a00297189c323096aae8e2975de94e8549613cyshang    OpenData->OpenCount         = 1;
117228a00297189c323096aae8e2975de94e8549613cyshang    InsertTailList (&Prot->OpenList, &OpenData->Link);
117328a00297189c323096aae8e2975de94e8549613cyshang    Prot->OpenListCount++;
117428a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_SUCCESS;
117528a00297189c323096aae8e2975de94e8549613cyshang  }
117628a00297189c323096aae8e2975de94e8549613cyshang
117728a00297189c323096aae8e2975de94e8549613cyshangDone:
117828a00297189c323096aae8e2975de94e8549613cyshang  //
117928a00297189c323096aae8e2975de94e8549613cyshang  // Done. Release the database lock are return
118028a00297189c323096aae8e2975de94e8549613cyshang  //
118128a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
118228a00297189c323096aae8e2975de94e8549613cyshang  return Status;
118328a00297189c323096aae8e2975de94e8549613cyshang}
118428a00297189c323096aae8e2975de94e8549613cyshang
118528a00297189c323096aae8e2975de94e8549613cyshang
1186162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1187162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
1188162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Closes a protocol on a handle that was opened using OpenProtocol().
1189162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1190022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle for the protocol interface that was
1191022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 previously opened with OpenProtocol(), and is
1192022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 now being closed.
1193022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The published unique identifier of the protocol.
1194022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 It is the caller's responsibility to pass in a
1195022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 valid GUID.
1196022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  AgentHandle            The handle of the agent that is closing the
1197022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 protocol interface.
1198022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ControllerHandle       If the agent that opened a protocol is a driver
1199022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 that follows the EFI Driver Model, then this
1200022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 parameter is the controller handle that required
1201022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 the protocol interface. If the agent does not
1202022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 follow the EFI Driver Model, then this parameter
1203022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 is optional and may be NULL.
1204022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
1205022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS            The protocol instance was closed.
1206022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  Handle, AgentHandle or ControllerHandle is not a
1207022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 valid EFI_HANDLE.
1208022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_NOT_FOUND          Can not find the specified protocol or
1209162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang                                 AgentHandle.
1210162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1211162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
121228a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
121328a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
121428a00297189c323096aae8e2975de94e8549613cyshangCoreCloseProtocol (
121528a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                UserHandle,
121628a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_GUID                  *Protocol,
121728a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                AgentHandle,
1218022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  IN  EFI_HANDLE                ControllerHandle
121928a00297189c323096aae8e2975de94e8549613cyshang  )
122028a00297189c323096aae8e2975de94e8549613cyshang{
122128a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS          Status;
122228a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE  *ProtocolInterface;
122328a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY          *Link;
122428a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA  *OpenData;
122528a00297189c323096aae8e2975de94e8549613cyshang
122628a00297189c323096aae8e2975de94e8549613cyshang  //
122728a00297189c323096aae8e2975de94e8549613cyshang  // Check for invalid parameters
122828a00297189c323096aae8e2975de94e8549613cyshang  //
122928a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (UserHandle);
123028a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
123128a00297189c323096aae8e2975de94e8549613cyshang    return Status;
123228a00297189c323096aae8e2975de94e8549613cyshang  }
123328a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (AgentHandle);
123428a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
123528a00297189c323096aae8e2975de94e8549613cyshang    return Status;
123628a00297189c323096aae8e2975de94e8549613cyshang  }
12374008328a99b99770764d1988e9fb2e12ce57e9f3qwang  if (ControllerHandle != NULL) {
123828a00297189c323096aae8e2975de94e8549613cyshang    Status = CoreValidateHandle (ControllerHandle);
123928a00297189c323096aae8e2975de94e8549613cyshang    if (EFI_ERROR (Status)) {
124028a00297189c323096aae8e2975de94e8549613cyshang      return Status;
124128a00297189c323096aae8e2975de94e8549613cyshang    }
124228a00297189c323096aae8e2975de94e8549613cyshang  }
124328a00297189c323096aae8e2975de94e8549613cyshang  if (Protocol == NULL) {
124428a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
124528a00297189c323096aae8e2975de94e8549613cyshang  }
124628a00297189c323096aae8e2975de94e8549613cyshang
124728a00297189c323096aae8e2975de94e8549613cyshang  //
124828a00297189c323096aae8e2975de94e8549613cyshang  // Lock the protocol database
124928a00297189c323096aae8e2975de94e8549613cyshang  //
125028a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
125128a00297189c323096aae8e2975de94e8549613cyshang
125228a00297189c323096aae8e2975de94e8549613cyshang  //
125328a00297189c323096aae8e2975de94e8549613cyshang  // Look at each protocol interface for a match
125428a00297189c323096aae8e2975de94e8549613cyshang  //
125528a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_NOT_FOUND;
125628a00297189c323096aae8e2975de94e8549613cyshang  ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
125728a00297189c323096aae8e2975de94e8549613cyshang  if (ProtocolInterface == NULL) {
125828a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
125928a00297189c323096aae8e2975de94e8549613cyshang  }
126028a00297189c323096aae8e2975de94e8549613cyshang
126128a00297189c323096aae8e2975de94e8549613cyshang  //
126228a00297189c323096aae8e2975de94e8549613cyshang  // Walk the Open data base looking for AgentHandle
126328a00297189c323096aae8e2975de94e8549613cyshang  //
126428a00297189c323096aae8e2975de94e8549613cyshang  Link = ProtocolInterface->OpenList.ForwardLink;
126528a00297189c323096aae8e2975de94e8549613cyshang  while (Link != &ProtocolInterface->OpenList) {
126628a00297189c323096aae8e2975de94e8549613cyshang    OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
126728a00297189c323096aae8e2975de94e8549613cyshang    Link = Link->ForwardLink;
126828a00297189c323096aae8e2975de94e8549613cyshang    if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) {
1269022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang        RemoveEntryList (&OpenData->Link);
127028a00297189c323096aae8e2975de94e8549613cyshang        ProtocolInterface->OpenListCount--;
127128a00297189c323096aae8e2975de94e8549613cyshang        CoreFreePool (OpenData);
127228a00297189c323096aae8e2975de94e8549613cyshang        Status = EFI_SUCCESS;
127328a00297189c323096aae8e2975de94e8549613cyshang    }
127428a00297189c323096aae8e2975de94e8549613cyshang  }
127528a00297189c323096aae8e2975de94e8549613cyshang
127628a00297189c323096aae8e2975de94e8549613cyshangDone:
127728a00297189c323096aae8e2975de94e8549613cyshang  //
127828a00297189c323096aae8e2975de94e8549613cyshang  // Done. Release the database lock and return.
127928a00297189c323096aae8e2975de94e8549613cyshang  //
128028a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
128128a00297189c323096aae8e2975de94e8549613cyshang  return Status;
128228a00297189c323096aae8e2975de94e8549613cyshang}
128328a00297189c323096aae8e2975de94e8549613cyshang
128428a00297189c323096aae8e2975de94e8549613cyshang
128528a00297189c323096aae8e2975de94e8549613cyshang
1286162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1287162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
1288162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Return information about Opened protocols in the system
1289162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1290022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle to close the protocol interface on
1291022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Protocol               The ID of the protocol
129211074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @param  EntryBuffer            A pointer to a buffer of open protocol information in the
129311074aabe131c7bcc850b1e95f567c205fff64fderic_tian                                 form of EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1294162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @param  EntryCount             Number of EntryBuffer entries
1295162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
129611074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @retval EFI_SUCCESS            The open protocol information was returned in EntryBuffer,
129711074aabe131c7bcc850b1e95f567c205fff64fderic_tian                                 and the number of entries was returned EntryCount.
129811074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @retval EFI_NOT_FOUND          Handle does not support the protocol specified by Protocol.
129911074aabe131c7bcc850b1e95f567c205fff64fderic_tian  @retval EFI_OUT_OF_RESOURCES   There are not enough resources available to allocate EntryBuffer.
130011074aabe131c7bcc850b1e95f567c205fff64fderic_tian
1301162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
130228a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
130328a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
130428a00297189c323096aae8e2975de94e8549613cyshangCoreOpenProtocolInformation (
130528a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_HANDLE                          UserHandle,
130628a00297189c323096aae8e2975de94e8549613cyshang  IN  EFI_GUID                            *Protocol,
130728a00297189c323096aae8e2975de94e8549613cyshang  OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
130828a00297189c323096aae8e2975de94e8549613cyshang  OUT UINTN                               *EntryCount
130928a00297189c323096aae8e2975de94e8549613cyshang  )
131028a00297189c323096aae8e2975de94e8549613cyshang{
131128a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                          Status;
131228a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                  *ProtocolInterface;
131328a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *Link;
131428a00297189c323096aae8e2975de94e8549613cyshang  OPEN_PROTOCOL_DATA                  *OpenData;
131528a00297189c323096aae8e2975de94e8549613cyshang  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer;
131628a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               Count;
131728a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               Size;
131828a00297189c323096aae8e2975de94e8549613cyshang
131928a00297189c323096aae8e2975de94e8549613cyshang  *EntryBuffer = NULL;
132028a00297189c323096aae8e2975de94e8549613cyshang  *EntryCount = 0;
132128a00297189c323096aae8e2975de94e8549613cyshang
132228a00297189c323096aae8e2975de94e8549613cyshang  //
132328a00297189c323096aae8e2975de94e8549613cyshang  // Lock the protocol database
132428a00297189c323096aae8e2975de94e8549613cyshang  //
132528a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
132628a00297189c323096aae8e2975de94e8549613cyshang
132728a00297189c323096aae8e2975de94e8549613cyshang  //
132828a00297189c323096aae8e2975de94e8549613cyshang  // Look at each protocol interface for a match
132928a00297189c323096aae8e2975de94e8549613cyshang  //
133028a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_NOT_FOUND;
133128a00297189c323096aae8e2975de94e8549613cyshang  ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol);
133228a00297189c323096aae8e2975de94e8549613cyshang  if (ProtocolInterface == NULL) {
133328a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
133428a00297189c323096aae8e2975de94e8549613cyshang  }
133528a00297189c323096aae8e2975de94e8549613cyshang
133628a00297189c323096aae8e2975de94e8549613cyshang  //
133728a00297189c323096aae8e2975de94e8549613cyshang  // Count the number of Open Entries
133828a00297189c323096aae8e2975de94e8549613cyshang  //
1339022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
134028a00297189c323096aae8e2975de94e8549613cyshang        (Link != &ProtocolInterface->OpenList) ;
134128a00297189c323096aae8e2975de94e8549613cyshang        Link = Link->ForwardLink  ) {
134228a00297189c323096aae8e2975de94e8549613cyshang    Count++;
1343022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  }
134428a00297189c323096aae8e2975de94e8549613cyshang
134528a00297189c323096aae8e2975de94e8549613cyshang  ASSERT (Count == ProtocolInterface->OpenListCount);
134628a00297189c323096aae8e2975de94e8549613cyshang
134728a00297189c323096aae8e2975de94e8549613cyshang  if (Count == 0) {
134828a00297189c323096aae8e2975de94e8549613cyshang    Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
134928a00297189c323096aae8e2975de94e8549613cyshang  } else {
135028a00297189c323096aae8e2975de94e8549613cyshang    Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY);
135128a00297189c323096aae8e2975de94e8549613cyshang  }
135228a00297189c323096aae8e2975de94e8549613cyshang
13539c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang  Buffer = AllocatePool (Size);
135428a00297189c323096aae8e2975de94e8549613cyshang  if (Buffer == NULL) {
135528a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_OUT_OF_RESOURCES;
135628a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
135728a00297189c323096aae8e2975de94e8549613cyshang  }
135828a00297189c323096aae8e2975de94e8549613cyshang
135928a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_SUCCESS;
1360022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0;
136128a00297189c323096aae8e2975de94e8549613cyshang        (Link != &ProtocolInterface->OpenList);
136228a00297189c323096aae8e2975de94e8549613cyshang        Link = Link->ForwardLink, Count++  ) {
136328a00297189c323096aae8e2975de94e8549613cyshang    OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
136428a00297189c323096aae8e2975de94e8549613cyshang
136528a00297189c323096aae8e2975de94e8549613cyshang    Buffer[Count].AgentHandle      = OpenData->AgentHandle;
136628a00297189c323096aae8e2975de94e8549613cyshang    Buffer[Count].ControllerHandle = OpenData->ControllerHandle;
136728a00297189c323096aae8e2975de94e8549613cyshang    Buffer[Count].Attributes       = OpenData->Attributes;
136828a00297189c323096aae8e2975de94e8549613cyshang    Buffer[Count].OpenCount        = OpenData->OpenCount;
1369022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  }
137028a00297189c323096aae8e2975de94e8549613cyshang
137128a00297189c323096aae8e2975de94e8549613cyshang  *EntryBuffer = Buffer;
137228a00297189c323096aae8e2975de94e8549613cyshang  *EntryCount = Count;
1373022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
137428a00297189c323096aae8e2975de94e8549613cyshangDone:
137528a00297189c323096aae8e2975de94e8549613cyshang  //
13761439777e96797cbf92e9748bd9b8ed1316099e3dqwang  // Done. Release the database lock.
137728a00297189c323096aae8e2975de94e8549613cyshang  //
137828a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
137928a00297189c323096aae8e2975de94e8549613cyshang  return Status;
138028a00297189c323096aae8e2975de94e8549613cyshang}
138128a00297189c323096aae8e2975de94e8549613cyshang
138228a00297189c323096aae8e2975de94e8549613cyshang
138328a00297189c323096aae8e2975de94e8549613cyshang
1384162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1385162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
1386162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1387162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  from pool.
1388162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1389022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  UserHandle             The handle from which to retrieve the list of
1390022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 protocol interface GUIDs.
1391022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ProtocolBuffer         A pointer to the list of protocol interface GUID
1392022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 pointers that are installed on Handle.
1393022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  ProtocolBufferCount    A pointer to the number of GUID pointers present
1394022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 in ProtocolBuffer.
1395022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
1396022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_SUCCESS            The list of protocol interface GUIDs installed
1397022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 on Handle was returned in ProtocolBuffer. The
1398022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 number of protocol interface GUIDs was returned
1399022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang                                 in ProtocolBufferCount.
1400022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  Handle is NULL.
1401022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  Handle is not a valid EFI_HANDLE.
1402022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  ProtocolBuffer is NULL.
1403022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_INVALID_PARAMETER  ProtocolBufferCount is NULL.
1404022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @retval EFI_OUT_OF_RESOURCES   There is not enough pool memory to store the
1405162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang                                 results.
1406162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1407162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
140828a00297189c323096aae8e2975de94e8549613cyshangEFI_STATUS
140928a00297189c323096aae8e2975de94e8549613cyshangEFIAPI
141028a00297189c323096aae8e2975de94e8549613cyshangCoreProtocolsPerHandle (
141128a00297189c323096aae8e2975de94e8549613cyshang  IN EFI_HANDLE       UserHandle,
141228a00297189c323096aae8e2975de94e8549613cyshang  OUT EFI_GUID        ***ProtocolBuffer,
141328a00297189c323096aae8e2975de94e8549613cyshang  OUT UINTN           *ProtocolBufferCount
141428a00297189c323096aae8e2975de94e8549613cyshang  )
141528a00297189c323096aae8e2975de94e8549613cyshang{
141628a00297189c323096aae8e2975de94e8549613cyshang  EFI_STATUS                          Status;
141728a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE                             *Handle;
141828a00297189c323096aae8e2975de94e8549613cyshang  PROTOCOL_INTERFACE                  *Prot;
141928a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY                          *Link;
142028a00297189c323096aae8e2975de94e8549613cyshang  UINTN                               ProtocolCount;
142128a00297189c323096aae8e2975de94e8549613cyshang  EFI_GUID                            **Buffer;
142228a00297189c323096aae8e2975de94e8549613cyshang
142328a00297189c323096aae8e2975de94e8549613cyshang  Status = CoreValidateHandle (UserHandle);
142428a00297189c323096aae8e2975de94e8549613cyshang  if (EFI_ERROR (Status)) {
142528a00297189c323096aae8e2975de94e8549613cyshang    return Status;
142628a00297189c323096aae8e2975de94e8549613cyshang  }
142728a00297189c323096aae8e2975de94e8549613cyshang
142828a00297189c323096aae8e2975de94e8549613cyshang  Handle = (IHANDLE *)UserHandle;
142928a00297189c323096aae8e2975de94e8549613cyshang
143028a00297189c323096aae8e2975de94e8549613cyshang  if (ProtocolBuffer == NULL) {
143128a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
143228a00297189c323096aae8e2975de94e8549613cyshang  }
143328a00297189c323096aae8e2975de94e8549613cyshang
143428a00297189c323096aae8e2975de94e8549613cyshang  if (ProtocolBufferCount == NULL) {
143528a00297189c323096aae8e2975de94e8549613cyshang    return EFI_INVALID_PARAMETER;
143628a00297189c323096aae8e2975de94e8549613cyshang  }
143728a00297189c323096aae8e2975de94e8549613cyshang
143828a00297189c323096aae8e2975de94e8549613cyshang  *ProtocolBufferCount = 0;
143928a00297189c323096aae8e2975de94e8549613cyshang
144028a00297189c323096aae8e2975de94e8549613cyshang  ProtocolCount = 0;
144128a00297189c323096aae8e2975de94e8549613cyshang
144228a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
1443022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
144428a00297189c323096aae8e2975de94e8549613cyshang  for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
144528a00297189c323096aae8e2975de94e8549613cyshang    ProtocolCount++;
144628a00297189c323096aae8e2975de94e8549613cyshang  }
144728a00297189c323096aae8e2975de94e8549613cyshang
144828a00297189c323096aae8e2975de94e8549613cyshang  //
144928a00297189c323096aae8e2975de94e8549613cyshang  // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE
145028a00297189c323096aae8e2975de94e8549613cyshang  //
145128a00297189c323096aae8e2975de94e8549613cyshang  if (ProtocolCount == 0) {
145228a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_INVALID_PARAMETER;
145328a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
145428a00297189c323096aae8e2975de94e8549613cyshang  }
145528a00297189c323096aae8e2975de94e8549613cyshang
14569c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang  Buffer = AllocatePool (sizeof (EFI_GUID *) * ProtocolCount);
145728a00297189c323096aae8e2975de94e8549613cyshang  if (Buffer == NULL) {
145828a00297189c323096aae8e2975de94e8549613cyshang    Status = EFI_OUT_OF_RESOURCES;
145928a00297189c323096aae8e2975de94e8549613cyshang    goto Done;
146028a00297189c323096aae8e2975de94e8549613cyshang  }
146128a00297189c323096aae8e2975de94e8549613cyshang
146228a00297189c323096aae8e2975de94e8549613cyshang  *ProtocolBuffer = Buffer;
146328a00297189c323096aae8e2975de94e8549613cyshang  *ProtocolBufferCount = ProtocolCount;
146428a00297189c323096aae8e2975de94e8549613cyshang
146528a00297189c323096aae8e2975de94e8549613cyshang  for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0;
1466022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang        Link != &Handle->Protocols;
146728a00297189c323096aae8e2975de94e8549613cyshang        Link = Link->ForwardLink, ProtocolCount++) {
146828a00297189c323096aae8e2975de94e8549613cyshang    Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
146928a00297189c323096aae8e2975de94e8549613cyshang    Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID);
147028a00297189c323096aae8e2975de94e8549613cyshang  }
147128a00297189c323096aae8e2975de94e8549613cyshang  Status = EFI_SUCCESS;
147228a00297189c323096aae8e2975de94e8549613cyshang
147328a00297189c323096aae8e2975de94e8549613cyshangDone:
147428a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
147528a00297189c323096aae8e2975de94e8549613cyshang  return Status;
147628a00297189c323096aae8e2975de94e8549613cyshang}
147728a00297189c323096aae8e2975de94e8549613cyshang
147828a00297189c323096aae8e2975de94e8549613cyshang
147928a00297189c323096aae8e2975de94e8549613cyshang
1480162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
148128a00297189c323096aae8e2975de94e8549613cyshang  return handle database key.
148228a00297189c323096aae8e2975de94e8549613cyshang
148328a00297189c323096aae8e2975de94e8549613cyshang
1484162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  @return Handle database key.
1485162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang
1486162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
1487162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangUINT64
1488162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreGetHandleDatabaseKey (
1489162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  VOID
1490162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
149128a00297189c323096aae8e2975de94e8549613cyshang{
149228a00297189c323096aae8e2975de94e8549613cyshang  return gHandleDatabaseKey;
149328a00297189c323096aae8e2975de94e8549613cyshang}
149428a00297189c323096aae8e2975de94e8549613cyshang
149528a00297189c323096aae8e2975de94e8549613cyshang
149628a00297189c323096aae8e2975de94e8549613cyshang
1497162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang/**
149828a00297189c323096aae8e2975de94e8549613cyshang  Go connect any handles that were created or modified while a image executed.
149928a00297189c323096aae8e2975de94e8549613cyshang
1500022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang  @param  Key                    The Key to show that the handle has been
1501162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang                                 created/modified
150228a00297189c323096aae8e2975de94e8549613cyshang
1503162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang**/
1504162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangVOID
1505162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuangCoreConnectHandlesByKey (
1506162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  UINT64  Key
1507162ed594438ab8d39f89b43e6d645ca24e1e1e65qhuang  )
150828a00297189c323096aae8e2975de94e8549613cyshang{
150928a00297189c323096aae8e2975de94e8549613cyshang  UINTN           Count;
151028a00297189c323096aae8e2975de94e8549613cyshang  LIST_ENTRY      *Link;
151128a00297189c323096aae8e2975de94e8549613cyshang  EFI_HANDLE      *HandleBuffer;
151228a00297189c323096aae8e2975de94e8549613cyshang  IHANDLE         *Handle;
151328a00297189c323096aae8e2975de94e8549613cyshang  UINTN           Index;
151428a00297189c323096aae8e2975de94e8549613cyshang
151528a00297189c323096aae8e2975de94e8549613cyshang  //
151628a00297189c323096aae8e2975de94e8549613cyshang  // Lock the protocol database
151728a00297189c323096aae8e2975de94e8549613cyshang  //
151828a00297189c323096aae8e2975de94e8549613cyshang  CoreAcquireProtocolLock ();
151928a00297189c323096aae8e2975de94e8549613cyshang
152028a00297189c323096aae8e2975de94e8549613cyshang  for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
152128a00297189c323096aae8e2975de94e8549613cyshang    Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
152228a00297189c323096aae8e2975de94e8549613cyshang    if (Handle->Key > Key) {
152328a00297189c323096aae8e2975de94e8549613cyshang      Count++;
152428a00297189c323096aae8e2975de94e8549613cyshang    }
152528a00297189c323096aae8e2975de94e8549613cyshang  }
152628a00297189c323096aae8e2975de94e8549613cyshang
15279c4ac31cca01b4a503c36616770ea3157bf3bb9eqhuang  HandleBuffer = AllocatePool (Count * sizeof (EFI_HANDLE));
152828a00297189c323096aae8e2975de94e8549613cyshang  if (HandleBuffer == NULL) {
152928a00297189c323096aae8e2975de94e8549613cyshang    CoreReleaseProtocolLock ();
153028a00297189c323096aae8e2975de94e8549613cyshang    return;
153128a00297189c323096aae8e2975de94e8549613cyshang  }
1532022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
153328a00297189c323096aae8e2975de94e8549613cyshang  for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) {
153428a00297189c323096aae8e2975de94e8549613cyshang    Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
153528a00297189c323096aae8e2975de94e8549613cyshang    if (Handle->Key > Key) {
153628a00297189c323096aae8e2975de94e8549613cyshang      HandleBuffer[Count++] = Handle;
153728a00297189c323096aae8e2975de94e8549613cyshang    }
153828a00297189c323096aae8e2975de94e8549613cyshang  }
153928a00297189c323096aae8e2975de94e8549613cyshang
154028a00297189c323096aae8e2975de94e8549613cyshang  //
154128a00297189c323096aae8e2975de94e8549613cyshang  // Unlock the protocol database
154228a00297189c323096aae8e2975de94e8549613cyshang  //
154328a00297189c323096aae8e2975de94e8549613cyshang  CoreReleaseProtocolLock ();
154428a00297189c323096aae8e2975de94e8549613cyshang
154528a00297189c323096aae8e2975de94e8549613cyshang  //
154628a00297189c323096aae8e2975de94e8549613cyshang  // Connect all handles whose Key value is greater than Key
154728a00297189c323096aae8e2975de94e8549613cyshang  //
154828a00297189c323096aae8e2975de94e8549613cyshang  for (Index = 0; Index < Count; Index++) {
154928a00297189c323096aae8e2975de94e8549613cyshang    CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
155028a00297189c323096aae8e2975de94e8549613cyshang  }
1551022c6d45ef78605c173023f53984e4dfaf7b11f4qhuang
155228a00297189c323096aae8e2975de94e8549613cyshang  CoreFreePool(HandleBuffer);
155328a00297189c323096aae8e2975de94e8549613cyshang}
1554