1 /** @file 2 Support functions for UEFI protocol notification infrastructure. 3 4 Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR> 5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "DxeMain.h" 17 #include "Handle.h" 18 #include "Event.h" 19 20 /** 21 Signal event for every protocol in protocol entry. 22 23 @param ProtEntry Protocol entry 24 25 **/ 26 VOID 27 CoreNotifyProtocolEntry ( 28 IN PROTOCOL_ENTRY *ProtEntry 29 ) 30 { 31 PROTOCOL_NOTIFY *ProtNotify; 32 LIST_ENTRY *Link; 33 34 ASSERT_LOCKED (&gProtocolDatabaseLock); 35 36 for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { 37 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); 38 CoreSignalEvent (ProtNotify->Event); 39 } 40 } 41 42 43 44 /** 45 Removes Protocol from the protocol list (but not the handle list). 46 47 @param Handle The handle to remove protocol on. 48 @param Protocol GUID of the protocol to be moved 49 @param Interface The interface of the protocol 50 51 @return Protocol Entry 52 53 **/ 54 PROTOCOL_INTERFACE * 55 CoreRemoveInterfaceFromProtocol ( 56 IN IHANDLE *Handle, 57 IN EFI_GUID *Protocol, 58 IN VOID *Interface 59 ) 60 { 61 PROTOCOL_INTERFACE *Prot; 62 PROTOCOL_NOTIFY *ProtNotify; 63 PROTOCOL_ENTRY *ProtEntry; 64 LIST_ENTRY *Link; 65 66 ASSERT_LOCKED (&gProtocolDatabaseLock); 67 68 Prot = CoreFindProtocolInterface (Handle, Protocol, Interface); 69 if (Prot != NULL) { 70 71 ProtEntry = Prot->Protocol; 72 73 // 74 // If there's a protocol notify location pointing to this entry, back it up one 75 // 76 for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { 77 ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); 78 79 if (ProtNotify->Position == &Prot->ByProtocol) { 80 ProtNotify->Position = Prot->ByProtocol.BackLink; 81 } 82 } 83 84 // 85 // Remove the protocol interface entry 86 // 87 RemoveEntryList (&Prot->ByProtocol); 88 } 89 90 return Prot; 91 } 92 93 94 /** 95 Add a new protocol notification record for the request protocol. 96 97 @param Protocol The requested protocol to add the notify 98 registration 99 @param Event The event to signal 100 @param Registration Returns the registration record 101 102 @retval EFI_INVALID_PARAMETER Invalid parameter 103 @retval EFI_SUCCESS Successfully returned the registration record 104 that has been added 105 106 **/ 107 EFI_STATUS 108 EFIAPI 109 CoreRegisterProtocolNotify ( 110 IN EFI_GUID *Protocol, 111 IN EFI_EVENT Event, 112 OUT VOID **Registration 113 ) 114 { 115 PROTOCOL_ENTRY *ProtEntry; 116 PROTOCOL_NOTIFY *ProtNotify; 117 EFI_STATUS Status; 118 119 if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) { 120 return EFI_INVALID_PARAMETER; 121 } 122 123 CoreAcquireProtocolLock (); 124 125 ProtNotify = NULL; 126 127 // 128 // Get the protocol entry to add the notification too 129 // 130 131 ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); 132 if (ProtEntry != NULL) { 133 134 // 135 // Allocate a new notification record 136 // 137 ProtNotify = AllocatePool (sizeof(PROTOCOL_NOTIFY)); 138 if (ProtNotify != NULL) { 139 ((IEVENT *)Event)->ExFlag |= EVT_EXFLAG_EVENT_PROTOCOL_NOTIFICATION; 140 ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; 141 ProtNotify->Protocol = ProtEntry; 142 ProtNotify->Event = Event; 143 // 144 // start at the begining 145 // 146 ProtNotify->Position = &ProtEntry->Protocols; 147 148 InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); 149 } 150 } 151 152 CoreReleaseProtocolLock (); 153 154 // 155 // Done. If we have a protocol notify entry, then return it. 156 // Otherwise, we must have run out of resources trying to add one 157 // 158 159 Status = EFI_OUT_OF_RESOURCES; 160 if (ProtNotify != NULL) { 161 *Registration = ProtNotify; 162 Status = EFI_SUCCESS; 163 } 164 165 return Status; 166 } 167 168 169 /** 170 Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. 171 172 @param UserHandle Handle on which the interface is to be 173 reinstalled 174 @param Protocol The numeric ID of the interface 175 @param OldInterface A pointer to the old interface 176 @param NewInterface A pointer to the new interface 177 178 @retval EFI_SUCCESS The protocol interface was installed 179 @retval EFI_NOT_FOUND The OldInterface on the handle was not found 180 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value 181 182 **/ 183 EFI_STATUS 184 EFIAPI 185 CoreReinstallProtocolInterface ( 186 IN EFI_HANDLE UserHandle, 187 IN EFI_GUID *Protocol, 188 IN VOID *OldInterface, 189 IN VOID *NewInterface 190 ) 191 { 192 EFI_STATUS Status; 193 IHANDLE *Handle; 194 PROTOCOL_INTERFACE *Prot; 195 PROTOCOL_ENTRY *ProtEntry; 196 197 Status = CoreValidateHandle (UserHandle); 198 if (EFI_ERROR (Status)) { 199 return Status; 200 } 201 202 if (Protocol == NULL) { 203 return EFI_INVALID_PARAMETER; 204 } 205 206 Handle = (IHANDLE *) UserHandle; 207 208 // 209 // Lock the protocol database 210 // 211 CoreAcquireProtocolLock (); 212 213 // 214 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database 215 // 216 Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface); 217 if (Prot == NULL) { 218 Status = EFI_NOT_FOUND; 219 goto Done; 220 } 221 222 // 223 // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled 224 // 225 Status = CoreDisconnectControllersUsingProtocolInterface ( 226 UserHandle, 227 Prot 228 ); 229 if (EFI_ERROR (Status)) { 230 // 231 // One or more drivers refused to release, so return the error 232 // 233 goto Done; 234 } 235 236 // 237 // Remove the protocol interface from the protocol 238 // 239 Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface); 240 241 if (Prot == NULL) { 242 Status = EFI_NOT_FOUND; 243 goto Done; 244 } 245 246 ProtEntry = Prot->Protocol; 247 248 // 249 // Update the interface on the protocol 250 // 251 Prot->Interface = NewInterface; 252 253 // 254 // Add this protocol interface to the tail of the 255 // protocol entry 256 // 257 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); 258 259 // 260 // Update the Key to show that the handle has been created/modified 261 // 262 gHandleDatabaseKey++; 263 Handle->Key = gHandleDatabaseKey; 264 265 // 266 // Release the lock and connect all drivers to UserHandle 267 // 268 CoreReleaseProtocolLock (); 269 // 270 // Return code is ignored on purpose. 271 // 272 CoreConnectController ( 273 UserHandle, 274 NULL, 275 NULL, 276 TRUE 277 ); 278 CoreAcquireProtocolLock (); 279 280 // 281 // Notify the notification list for this protocol 282 // 283 CoreNotifyProtocolEntry (ProtEntry); 284 285 Status = EFI_SUCCESS; 286 287 Done: 288 CoreReleaseProtocolLock (); 289 290 return Status; 291 } 292