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