IScsiDriver.c revision e48e37fce2611df7a52aff271835ff72ee396d9b
1/*++ 2 3Copyright (c) 2004 - 2007, Intel Corporation 4All rights reserved. This program and the accompanying materials 5are licensed and made available under the terms and conditions of the BSD License 6which accompanies this distribution. The full text of the license may be found at 7http://opensource.org/licenses/bsd-license.php 8 9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12Module Name: 13 14 IScsiDriver.c 15 16Abstract: 17 18--*/ 19 20#include "IScsiImpl.h" 21 22EFI_DRIVER_BINDING_PROTOCOL gIScsiDriverBinding = { 23 IScsiDriverBindingSupported, 24 IScsiDriverBindingStart, 25 IScsiDriverBindingStop, 26 0xa, 27 NULL, 28 NULL 29}; 30 31EFI_GUID mIScsiPrivateGuid = ISCSI_PRIVATE_GUID; 32 33EFI_STATUS 34EFIAPI 35IScsiDriverBindingSupported ( 36 IN EFI_DRIVER_BINDING_PROTOCOL * This, 37 IN EFI_HANDLE ControllerHandle, 38 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL 39 ) 40/*++ 41 42Routine Description: 43 44 Test to see if iSCSI driver supports the given controller. 45 46Arguments: 47 48 This - Protocol instance pointer. 49 ControllerHandle - Handle of controller to test. 50 RemainingDevicePath - Optional parameter use to pick a specific child device to start. 51 52Returns: 53 54 EFI_SUCCES - This driver supports the controller. 55 EFI_ALREADY_STARTED - This driver is already running on this device. 56 EFI_UNSUPPORTED - This driver doesn't support the controller. 57 58--*/ 59{ 60 EFI_STATUS Status; 61 EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; 62 63 Status = gBS->OpenProtocol ( 64 ControllerHandle, 65 &mIScsiPrivateGuid, 66 NULL, 67 This->DriverBindingHandle, 68 ControllerHandle, 69 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 70 ); 71 if (!EFI_ERROR (Status)) { 72 return EFI_ALREADY_STARTED; 73 } 74 75 Status = gBS->OpenProtocol ( 76 ControllerHandle, 77 &gEfiTcp4ServiceBindingProtocolGuid, 78 NULL, 79 This->DriverBindingHandle, 80 ControllerHandle, 81 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 82 ); 83 if (EFI_ERROR (Status)) { 84 return EFI_UNSUPPORTED; 85 } 86 87 CurrentDevicePath = RemainingDevicePath; 88 if (CurrentDevicePath != NULL) { 89 while (!IsDevicePathEnd (CurrentDevicePath)) { 90 if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) { 91 return EFI_SUCCESS; 92 } 93 94 CurrentDevicePath = NextDevicePathNode (CurrentDevicePath); 95 } 96 97 return EFI_UNSUPPORTED; 98 } 99 100 return EFI_SUCCESS; 101} 102 103EFI_STATUS 104EFIAPI 105IScsiDriverBindingStart ( 106 IN EFI_DRIVER_BINDING_PROTOCOL * This, 107 IN EFI_HANDLE ControllerHandle, 108 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL 109 ) 110/*++ 111 112Routine Description: 113 114 Start to manage the controller. 115 116Arguments: 117 118 This - Protocol instance pointer. 119 ControllerHandle - Handle of the controller. 120 RemainingDevicePath - Optional parameter use to pick a specific child device to start. 121 122Returns: 123 124 EFI_SUCCES - This driver supports this device. 125 EFI_ALREADY_STARTED - This driver is already running on this device. 126 127--*/ 128{ 129 EFI_STATUS Status; 130 ISCSI_DRIVER_DATA *Private; 131 132 // 133 // Try to add a port configuration page for this controller. 134 // 135 IScsiConfigUpdateForm (This->DriverBindingHandle, ControllerHandle, TRUE); 136 137 Private = IScsiCreateDriverData (This->DriverBindingHandle, ControllerHandle); 138 if (Private == NULL) { 139 return EFI_OUT_OF_RESOURCES; 140 } 141 // 142 // Get the iSCSI configuration data of this controller. 143 // 144 Status = IScsiGetConfigData (Private); 145 if (EFI_ERROR (Status)) { 146 goto ON_ERROR; 147 } 148 // 149 // Try to login and create an iSCSI session according to the configuration. 150 // 151 Status = IScsiSessionLogin (Private); 152 if (Status == EFI_MEDIA_CHANGED) { 153 // 154 // The specified target is not available and the redirection information is 155 // got, login the session again with the updated target address. 156 // 157 Status = IScsiSessionLogin (Private); 158 } 159 160 if (EFI_ERROR (Status)) { 161 goto ON_ERROR; 162 } 163 // 164 // Duplicate the Session's tcp connection device path. The source port field 165 // will be set to zero as one iSCSI session is comprised of several iSCSI 166 // connections. 167 // 168 Private->DevicePath = IScsiGetTcpConnDevicePath (Private); 169 if (Private->DevicePath == NULL) { 170 goto ON_ERROR; 171 } 172 // 173 // Install the updated device path onto the ExtScsiPassThruHandle. 174 // 175 Status = gBS->InstallProtocolInterface ( 176 &Private->ExtScsiPassThruHandle, 177 &gEfiDevicePathProtocolGuid, 178 EFI_NATIVE_INTERFACE, 179 Private->DevicePath 180 ); 181 if (EFI_ERROR (Status)) { 182 goto ON_ERROR; 183 } 184 // 185 // Install the iSCSI private stuff as a flag to indicate this controller 186 // is already controlled by iSCSI driver. 187 // 188 Status = gBS->InstallProtocolInterface ( 189 &ControllerHandle, 190 &mIScsiPrivateGuid, 191 EFI_NATIVE_INTERFACE, 192 &Private->IScsiIdentifier 193 ); 194 if (EFI_ERROR (Status)) { 195 goto ON_ERROR; 196 } 197 // 198 // Update/Publish the iSCSI Boot Firmware Table. 199 // 200 IScsiPublishIbft (); 201 202 return EFI_SUCCESS; 203 204ON_ERROR: 205 206 IScsiSessionAbort (&Private->Session); 207 IScsiCleanDriverData (Private); 208 209 return Status; 210} 211 212EFI_STATUS 213EFIAPI 214IScsiDriverBindingStop ( 215 IN EFI_DRIVER_BINDING_PROTOCOL *This, 216 IN EFI_HANDLE ControllerHandle, 217 IN UINTN NumberOfChildren, 218 IN EFI_HANDLE *ChildHandleBuffer 219 ) 220/*++ 221 222Routine Description: 223 224 Release the control of this controller and remove the iSCSI functions. 225 226Arguments: 227 228 This - Protocol instance pointer. 229 ControllerHandle - Handle of controller to stop. 230 NumberOfChildren - Not used. 231 ChildHandleBuffer - Not used. 232 233Returns: 234 235 EFI_SUCCES - This driver supports this device. 236 237--*/ 238{ 239 EFI_HANDLE IScsiController; 240 EFI_STATUS Status; 241 ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier; 242 ISCSI_DRIVER_DATA *Private; 243 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru; 244 ISCSI_CONNECTION *Conn; 245 246 if (NumberOfChildren != 0) { 247 // 248 // We should have only one child. 249 // 250 Status = gBS->OpenProtocol ( 251 ChildHandleBuffer[0], 252 &gEfiExtScsiPassThruProtocolGuid, 253 (VOID **) &PassThru, 254 This->DriverBindingHandle, 255 ControllerHandle, 256 EFI_OPEN_PROTOCOL_GET_PROTOCOL 257 ); 258 if (EFI_ERROR (Status)) { 259 return EFI_DEVICE_ERROR; 260 } 261 262 Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru); 263 Conn = NET_LIST_HEAD (&Private->Session.Conns, ISCSI_CONNECTION, Link); 264 265 // 266 // Previously the TCP4 protocol is opened BY_CHILD_CONTROLLER. Just close 267 // the protocol here but not uninstall the device path protocol and 268 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle. 269 // 270 gBS->CloseProtocol ( 271 Conn->Tcp4Io.Handle, 272 &gEfiTcp4ProtocolGuid, 273 Private->Image, 274 Private->ExtScsiPassThruHandle 275 ); 276 277 return EFI_SUCCESS; 278 } 279 // 280 // Get the handle of the controller we are controling. 281 // 282 IScsiController = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid); 283 284 Status = gBS->OpenProtocol ( 285 IScsiController, 286 &mIScsiPrivateGuid, 287 (VOID **)&IScsiIdentifier, 288 This->DriverBindingHandle, 289 ControllerHandle, 290 EFI_OPEN_PROTOCOL_GET_PROTOCOL 291 ); 292 if (EFI_ERROR (Status)) { 293 return EFI_DEVICE_ERROR; 294 } 295 296 Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier); 297 298 // 299 // Uninstall the private protocol. 300 // 301 gBS->UninstallProtocolInterface ( 302 IScsiController, 303 &mIScsiPrivateGuid, 304 &Private->IScsiIdentifier 305 ); 306 307 // 308 // Update the iSCSI Boot Firware Table. 309 // 310 IScsiPublishIbft (); 311 312 IScsiSessionAbort (&Private->Session); 313 IScsiCleanDriverData (Private); 314 315 return EFI_SUCCESS; 316} 317 318EFI_STATUS 319EFIAPI 320EfiIScsiUnload ( 321 IN EFI_HANDLE ImageHandle 322 ) 323/*++ 324 325Routine Description: 326 327 Unload the iSCSI driver. 328 329Arguments: 330 331 ImageHandle - The handle of the driver image. 332 333Returns: 334 335 EFI_SUCCESS - The driver is unloaded. 336 EFI_DEVICE_ERROR - Some unexpected error happened. 337 338--*/ 339{ 340 EFI_STATUS Status; 341 UINTN DeviceHandleCount; 342 EFI_HANDLE *DeviceHandleBuffer; 343 UINTN Index; 344 345 // 346 // Try to disonnect the driver from the devices it's controlling. 347 // 348 Status = gBS->LocateHandleBuffer ( 349 AllHandles, 350 NULL, 351 NULL, 352 &DeviceHandleCount, 353 &DeviceHandleBuffer 354 ); 355 if (!EFI_ERROR (Status)) { 356 for (Index = 0; Index < DeviceHandleCount; Index++) { 357 Status = gBS->DisconnectController ( 358 DeviceHandleBuffer[Index], 359 ImageHandle, 360 NULL 361 ); 362 } 363 364 if (DeviceHandleBuffer != NULL) { 365 gBS->FreePool (DeviceHandleBuffer); 366 } 367 } 368 // 369 // Unload the iSCSI configuration form. 370 // 371 IScsiConfigFormUnload (gIScsiDriverBinding.DriverBindingHandle); 372 373 // 374 // Uninstall the protocols installed by iSCSI driver. 375 // 376 Status = gBS->UninstallMultipleProtocolInterfaces ( 377 ImageHandle, 378 &gEfiDriverBindingProtocolGuid, 379 &gIScsiDriverBinding, 380 &gEfiComponentName2ProtocolGuid, 381 &gIScsiComponentName2, 382 &gEfiComponentNameProtocolGuid, 383 &gIScsiComponentName, 384 &gEfiIScsiInitiatorNameProtocolGuid, 385 &gIScsiInitiatorName, 386 NULL 387 ); 388 389 return Status; 390} 391 392EFI_STATUS 393EFIAPI 394IScsiDriverEntryPoint ( 395 IN EFI_HANDLE ImageHandle, 396 IN EFI_SYSTEM_TABLE *SystemTable 397 ) 398/*++ 399 400Routine Description: 401 402 Initialize the global variables publish the driver binding protocol. 403 404Arguments: 405 406 ImageHandle - The handle of the driver image. 407 SystemTable - The EFI system table. 408 409Returns: 410 411 EFI_SUCCESS - The protocols are installed. 412 EFI_DEVICE_ERROR - Some unexpected error happened. 413 414--*/ 415{ 416 EFI_STATUS Status; 417 //EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 418 419 // 420 // Initialize the EFI Driver Library 421 // 422 Status = EfiLibInstallDriverBindingComponentName2 ( 423 ImageHandle, 424 SystemTable, 425 &gIScsiDriverBinding, 426 ImageHandle, 427 &gIScsiComponentName, 428 &gIScsiComponentName2 429 ); 430 431 if (EFI_ERROR (Status)) { 432 return Status; 433 } 434 435 if (!EFI_ERROR (Status)) { 436 Status = gBS->InstallProtocolInterface ( 437 &ImageHandle, 438 &gEfiIScsiInitiatorNameProtocolGuid, 439 EFI_NATIVE_INTERFACE, 440 &gIScsiInitiatorName 441 ); 442 if (EFI_ERROR (Status)) { 443 gBS->UninstallMultipleProtocolInterfaces ( 444 ImageHandle, 445 &gEfiDriverBindingProtocolGuid, 446 &gIScsiDriverBinding, 447 &gEfiComponentName2ProtocolGuid, 448 &gIScsiComponentName2, 449 &gEfiComponentNameProtocolGuid, 450 &gIScsiComponentName, 451 NULL 452 ); 453 } 454 } 455 // 456 // Initialize the configuration form of iSCSI. 457 // 458 IScsiConfigFormInit (gIScsiDriverBinding.DriverBindingHandle); 459 460 return Status; 461} 462 463