2 The entry point of IScsi driver.
4 Copyright (c) 2004 - 2016, 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
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.
15 #include "IScsiImpl.h"
17 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding
= {
18 IScsiIp4DriverBindingSupported
,
19 IScsiIp4DriverBindingStart
,
20 IScsiIp4DriverBindingStop
,
26 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding
= {
27 IScsiIp6DriverBindingSupported
,
28 IScsiIp6DriverBindingStart
,
29 IScsiIp6DriverBindingStop
,
35 EFI_GUID gIScsiV4PrivateGuid
= ISCSI_V4_PRIVATE_GUID
;
36 EFI_GUID gIScsiV6PrivateGuid
= ISCSI_V6_PRIVATE_GUID
;
37 ISCSI_PRIVATE_DATA
*mPrivate
= NULL
;
40 Tests to see if this driver supports the RemainingDevicePath.
42 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
43 parameter is ignored by device drivers, and is optional for bus
44 drivers. For bus drivers, if this parameter is not NULL, then
45 the bus driver must determine if the bus controller specified
46 by ControllerHandle and the child controller specified
47 by RemainingDevicePath are both supported by this
50 @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.
51 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
52 RemainingDevicePath is not supported by the driver specified by This.
55 IScsiIsDevicePathSupported (
56 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
59 EFI_DEVICE_PATH_PROTOCOL
*CurrentDevicePath
;
61 CurrentDevicePath
= RemainingDevicePath
;
62 if (CurrentDevicePath
!= NULL
) {
63 while (!IsDevicePathEnd (CurrentDevicePath
)) {
64 if ((CurrentDevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (CurrentDevicePath
->SubType
== MSG_ISCSI_DP
)) {
68 CurrentDevicePath
= NextDevicePathNode (CurrentDevicePath
);
71 return EFI_UNSUPPORTED
;
78 Check whether an iSCSI HBA adapter already installs an AIP instance with
79 network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.
80 If yes, return EFI_SUCCESS.
82 @retval EFI_SUCCESS Found an AIP with matching network boot policy.
83 @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy
91 EFI_HANDLE
*AipHandleBuffer
;
93 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
94 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExtScsiPassThru
;
95 EFI_GUID
*InfoTypesBuffer
;
96 UINTN InfoTypeBufferCount
;
101 EFI_ADAPTER_INFO_NETWORK_BOOT
*NetworkBoot
;
103 UINT8 NetworkBootPolicy
;
106 // Check any AIP instances exist in system.
109 AipHandleBuffer
= NULL
;
110 Status
= gBS
->LocateHandleBuffer (
112 &gEfiAdapterInformationProtocolGuid
,
117 if (EFI_ERROR (Status
) || AipHandleCount
== 0) {
118 return EFI_NOT_FOUND
;
121 ASSERT (AipHandleBuffer
!= NULL
);
125 for (AipIndex
= 0; AipIndex
< AipHandleCount
; AipIndex
++) {
126 Status
= gBS
->HandleProtocol (
127 AipHandleBuffer
[AipIndex
],
128 &gEfiAdapterInformationProtocolGuid
,
131 ASSERT_EFI_ERROR (Status
);
132 ASSERT (Aip
!= NULL
);
134 Status
= gBS
->HandleProtocol (
135 AipHandleBuffer
[AipIndex
],
136 &gEfiExtScsiPassThruProtocolGuid
,
137 (VOID
*) &ExtScsiPassThru
139 if (EFI_ERROR (Status
) || ExtScsiPassThru
== NULL
) {
143 InfoTypesBuffer
= NULL
;
144 InfoTypeBufferCount
= 0;
145 Status
= Aip
->GetSupportedTypes (Aip
, &InfoTypesBuffer
, &InfoTypeBufferCount
);
146 if (EFI_ERROR (Status
) || InfoTypesBuffer
== NULL
) {
150 // Check whether the AIP instance has Network boot information block.
153 for (TypeIndex
= 0; TypeIndex
< InfoTypeBufferCount
; TypeIndex
++) {
154 if (CompareGuid (&InfoTypesBuffer
[TypeIndex
], &gEfiAdapterInfoNetworkBootGuid
)) {
160 FreePool (InfoTypesBuffer
);
166 // We now have network boot information block.
170 Status
= Aip
->GetInformation (Aip
, &gEfiAdapterInfoNetworkBootGuid
, &InfoBlock
, &InfoBlockSize
);
171 if (EFI_ERROR (Status
) || InfoBlock
== NULL
) {
176 // Check whether the network boot policy matches.
178 NetworkBoot
= (EFI_ADAPTER_INFO_NETWORK_BOOT
*) InfoBlock
;
179 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
181 if (NetworkBootPolicy
== STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP
) {
182 Status
= EFI_SUCCESS
;
185 if (((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4
) != 0 &&
186 !NetworkBoot
->iScsiIpv4BootCapablity
) ||
187 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6
) != 0 &&
188 !NetworkBoot
->iScsiIpv6BootCapablity
) ||
189 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD
) != 0 &&
190 !NetworkBoot
->OffloadCapability
) ||
191 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO
) != 0 &&
192 !NetworkBoot
->iScsiMpioCapability
) ||
193 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4
) != 0 &&
194 !NetworkBoot
->iScsiIpv4Boot
) ||
195 ((NetworkBootPolicy
& STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6
) != 0 &&
196 !NetworkBoot
->iScsiIpv6Boot
)) {
197 FreePool (InfoBlock
);
201 Status
= EFI_SUCCESS
;
205 Status
= EFI_NOT_FOUND
;
208 if (InfoBlock
!= NULL
) {
209 FreePool (InfoBlock
);
211 if (AipHandleBuffer
!= NULL
) {
212 FreePool (AipHandleBuffer
);
218 Tests to see if this driver supports a given controller. This is the worker function for
219 IScsiIp4(6)DriverBindingSupported.
221 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
222 @param[in] ControllerHandle The handle of the controller to test. This handle
223 must support a protocol interface that supplies
224 an I/O abstraction to the driver.
225 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
226 parameter is ignored by device drivers, and is optional for bus
227 drivers. For bus drivers, if this parameter is not NULL, then
228 the bus driver must determine if the bus controller specified
229 by ControllerHandle and the child controller specified
230 by RemainingDevicePath are both supported by this
232 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
234 @retval EFI_SUCCESS The device specified by ControllerHandle and
235 RemainingDevicePath is supported by the driver specified by This.
236 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
237 RemainingDevicePath is already being managed by the driver
239 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
240 RemainingDevicePath is not supported by the driver specified by This.
245 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
246 IN EFI_HANDLE ControllerHandle
,
247 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
,
252 EFI_GUID
*IScsiServiceBindingGuid
;
253 EFI_GUID
*TcpServiceBindingGuid
;
254 EFI_GUID
*DhcpServiceBindingGuid
;
256 if (IpVersion
== IP_VERSION_4
) {
257 IScsiServiceBindingGuid
= &gIScsiV4PrivateGuid
;
258 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
259 DhcpServiceBindingGuid
= &gEfiDhcp4ServiceBindingProtocolGuid
;
261 IScsiServiceBindingGuid
= &gIScsiV6PrivateGuid
;
262 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
263 DhcpServiceBindingGuid
= &gEfiDhcp6ServiceBindingProtocolGuid
;
266 Status
= gBS
->OpenProtocol (
268 IScsiServiceBindingGuid
,
270 This
->DriverBindingHandle
,
272 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
274 if (!EFI_ERROR (Status
)) {
275 return EFI_ALREADY_STARTED
;
278 Status
= gBS
->OpenProtocol (
280 TcpServiceBindingGuid
,
282 This
->DriverBindingHandle
,
284 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
286 if (EFI_ERROR (Status
)) {
287 return EFI_UNSUPPORTED
;
290 Status
= IScsiIsDevicePathSupported (RemainingDevicePath
);
291 if (EFI_ERROR (Status
)) {
292 return EFI_UNSUPPORTED
;
295 if (IScsiDhcpIsConfigured (ControllerHandle
, IpVersion
)) {
296 Status
= gBS
->OpenProtocol (
298 DhcpServiceBindingGuid
,
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
304 if (EFI_ERROR (Status
)) {
305 return EFI_UNSUPPORTED
;
314 Start to manage the controller. This is the worker function for
315 IScsiIp4(6)DriverBindingStart.
317 @param[in] Image Handle of the image.
318 @param[in] ControllerHandle Handle of the controller.
319 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
321 @retval EFI_SUCCES This driver was started.
322 @retval EFI_ALREADY_STARTED This driver is already running on this device.
323 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
324 @retval EFI_NOT_FOUND There is no sufficient information to establish
326 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
327 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
328 because its interfaces are being used.
334 IN EFI_HANDLE ControllerHandle
,
339 ISCSI_DRIVER_DATA
*Private
;
341 LIST_ENTRY
*NextEntry
;
342 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
343 ISCSI_SESSION
*Session
;
345 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExistIScsiExtScsiPassThru
;
346 ISCSI_DRIVER_DATA
*ExistPrivate
;
347 UINT8
*AttemptConfigOrder
;
348 UINTN AttemptConfigOrderSize
;
350 EFI_HANDLE
*HandleBuffer
;
351 UINTN NumberOfHandles
;
352 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
353 EFI_GUID
*IScsiPrivateGuid
;
354 EFI_GUID
*TcpServiceBindingGuid
;
355 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
358 EFI_GUID
*ProtocolGuid
;
359 UINT8 NetworkBootPolicy
;
362 // Test to see if iSCSI driver supports the given controller.
365 if (IpVersion
== IP_VERSION_4
) {
366 IScsiPrivateGuid
= &gIScsiV4PrivateGuid
;
367 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
368 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
369 } else if (IpVersion
== IP_VERSION_6
) {
370 IScsiPrivateGuid
= &gIScsiV6PrivateGuid
;
371 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
372 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
374 return EFI_INVALID_PARAMETER
;
377 Status
= gBS
->OpenProtocol (
383 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
385 if (!EFI_ERROR (Status
)) {
386 return EFI_ALREADY_STARTED
;
389 Status
= gBS
->OpenProtocol (
391 TcpServiceBindingGuid
,
395 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
397 if (EFI_ERROR (Status
)) {
398 return EFI_UNSUPPORTED
;
401 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
402 if (NetworkBootPolicy
!= ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_AIP
) {
404 // Check existing iSCSI AIP.
406 Status
= IScsiCheckAip ();
407 if (!EFI_ERROR (Status
)) {
409 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
416 // Record the incoming NIC info.
418 Status
= IScsiAddNic (ControllerHandle
);
419 if (EFI_ERROR (Status
)) {
424 // Create the instance private data.
426 Private
= IScsiCreateDriverData (Image
, ControllerHandle
);
427 if (Private
== NULL
) {
428 return EFI_OUT_OF_RESOURCES
;
432 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
433 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
434 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
435 // IScsiDriverBindingStop() will be called.
437 Status
= NetLibCreateServiceChild (
440 TcpServiceBindingGuid
,
441 &Private
->ChildHandle
444 if (EFI_ERROR (Status
)) {
448 Status
= gBS
->OpenProtocol (
449 Private
->ChildHandle
, /// Default Tcp child
454 EFI_OPEN_PROTOCOL_BY_DRIVER
457 if (EFI_ERROR (Status
)) {
462 // Always install private protocol no matter what happens later. We need to
463 // keep the relationship between ControllerHandle and ChildHandle.
465 Status
= gBS
->InstallProtocolInterface (
468 EFI_NATIVE_INTERFACE
,
469 &Private
->IScsiIdentifier
471 if (EFI_ERROR (Status
)) {
475 if (IpVersion
== IP_VERSION_4
) {
476 mPrivate
->Ipv6Flag
= FALSE
;
478 mPrivate
->Ipv6Flag
= TRUE
;
482 // Get the current iSCSI configuration data.
484 Status
= IScsiGetConfigData (Private
);
485 if (EFI_ERROR (Status
)) {
490 // If there is already a successul attempt, check whether this attempt is the
491 // first "enabled for MPIO" attempt. If not, still try the first attempt.
492 // In single path mode, try all attempts.
495 Status
= EFI_NOT_FOUND
;
497 if (mPrivate
->OneSessionEstablished
&& mPrivate
->EnableMpio
) {
498 AttemptConfigData
= NULL
;
499 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
500 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
501 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
506 if (AttemptConfigData
== NULL
) {
510 if (AttemptConfigData
->AttemptConfigIndex
== mPrivate
->BootSelectedIndex
) {
515 // Uninstall the original ExtScsiPassThru first.
519 // Locate all ExtScsiPassThru protocol instances.
521 Status
= gBS
->LocateHandleBuffer (
523 &gEfiExtScsiPassThruProtocolGuid
,
528 if (EFI_ERROR (Status
)) {
533 // Find ExtScsiPassThru protocol instance produced by this driver.
535 ExistIScsiExtScsiPassThru
= NULL
;
536 for (Index
= 0; Index
< NumberOfHandles
&& ExistIScsiExtScsiPassThru
== NULL
; Index
++) {
537 Status
= gBS
->HandleProtocol (
539 &gEfiDevicePathProtocolGuid
,
540 (VOID
**) &DevicePath
542 if (EFI_ERROR (Status
)) {
546 while (!IsDevicePathEnd (DevicePath
)) {
547 if ((DevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (DevicePath
->SubType
== MSG_MAC_ADDR_DP
)) {
549 // Get the ExtScsiPassThru protocol instance.
551 Status
= gBS
->HandleProtocol (
553 &gEfiExtScsiPassThruProtocolGuid
,
554 (VOID
**) &ExistIScsiExtScsiPassThru
556 ASSERT_EFI_ERROR (Status
);
560 DevicePath
= NextDevicePathNode (DevicePath
);
564 FreePool (HandleBuffer
);
566 if (ExistIScsiExtScsiPassThru
== NULL
) {
567 Status
= EFI_NOT_FOUND
;
571 ExistPrivate
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru
);
573 Status
= gBS
->UninstallProtocolInterface (
574 ExistPrivate
->ExtScsiPassThruHandle
,
575 &gEfiExtScsiPassThruProtocolGuid
,
576 &ExistPrivate
->IScsiExtScsiPassThru
578 if (EFI_ERROR (Status
)) {
584 // Install the Ext SCSI PASS THRU protocol.
586 Status
= gBS
->InstallProtocolInterface (
587 &Private
->ExtScsiPassThruHandle
,
588 &gEfiExtScsiPassThruProtocolGuid
,
589 EFI_NATIVE_INTERFACE
,
590 &Private
->IScsiExtScsiPassThru
592 if (EFI_ERROR (Status
)) {
598 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
599 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
601 // Don't process the attempt that does not associate with the current NIC or
602 // this attempt is disabled or established.
604 if (AttemptConfigData
->NicIndex
!= mPrivate
->CurrentNic
||
605 AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_DISABLED
||
606 AttemptConfigData
->ValidPath
) {
611 // In multipath mode, don't process attempts configured for single path.
612 // In default single path mode, don't process attempts configured for multipath.
614 if ((mPrivate
->EnableMpio
&&
615 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED_FOR_MPIO
) ||
616 (!mPrivate
->EnableMpio
&&
617 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED
)) {
622 // Don't process the attempt that fails to get the init/target information from DHCP.
624 if (AttemptConfigData
->SessionConfigData
.InitiatorInfoFromDhcp
&&
625 !AttemptConfigData
->DhcpSuccess
) {
626 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
627 mPrivate
->ValidSinglePathCount
--;
633 // Don't process the autoconfigure path if it is already established.
635 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
636 AttemptConfigData
->AutoConfigureSuccess
) {
641 // Don't process the attempt if its IP mode is not in the current IP version.
643 if (!mPrivate
->Ipv6Flag
) {
644 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP6
) {
647 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
648 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP6
) {
652 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP4
) {
655 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
656 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP4
) {
662 // Fill in the Session and init it.
664 Session
= (ISCSI_SESSION
*) AllocateZeroPool (sizeof (ISCSI_SESSION
));
665 if (Session
== NULL
) {
666 Status
= EFI_OUT_OF_RESOURCES
;
670 Session
->Private
= Private
;
671 Session
->ConfigData
= AttemptConfigData
;
672 Session
->AuthType
= AttemptConfigData
->AuthenticationType
;
674 AsciiStrToUnicodeStr (AttemptConfigData
->MacString
, MacString
);
676 mPrivate
->PortString
,
677 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
680 (UINTN
) AttemptConfigData
->AttemptConfigIndex
683 if (Session
->AuthType
== ISCSI_AUTH_TYPE_CHAP
) {
684 Session
->AuthData
.CHAP
.AuthConfig
= &AttemptConfigData
->AuthConfigData
.CHAP
;
687 IScsiSessionInit (Session
, FALSE
);
690 // Try to login and create an iSCSI session according to the configuration.
692 Status
= IScsiSessionLogin (Session
);
693 if (Status
== EFI_MEDIA_CHANGED
) {
695 // The specified target is not available, and the redirection information is
696 // received. Login the session again with the updated target address.
698 Status
= IScsiSessionLogin (Session
);
699 } else if (Status
== EFI_NOT_READY
) {
700 Status
= IScsiSessionReLogin (Session
);
703 if (EFI_ERROR (Status
)) {
705 // In Single path mode, only the successful attempt will be recorded in iBFT;
706 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
708 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
709 mPrivate
->ValidSinglePathCount
--;
715 AttemptConfigData
->ValidPath
= TRUE
;
718 // Do not record the attempt in iBFT if it login with KRB5.
719 // TODO: record KRB5 attempt information in the iSCSI device path.
721 if (Session
->AuthType
== ISCSI_AUTH_TYPE_KRB
) {
722 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
723 mPrivate
->ValidSinglePathCount
--;
726 AttemptConfigData
->ValidiBFTPath
= FALSE
;
728 AttemptConfigData
->ValidiBFTPath
= TRUE
;
732 // IScsi session success. Update the attempt state to NVR.
734 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) {
735 AttemptConfigData
->AutoConfigureSuccess
= TRUE
;
739 mPrivate
->PortString
,
740 &gEfiIScsiInitiatorNameProtocolGuid
,
741 ISCSI_CONFIG_VAR_ATTR
,
742 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
747 // Select the first login session. Abort others.
749 if (Private
->Session
== NULL
) {
750 Private
->Session
= Session
;
751 BootSelected
= AttemptConfigData
->AttemptConfigIndex
;
753 // Don't validate other attempt in multipath mode if one is success.
755 if (mPrivate
->EnableMpio
) {
759 IScsiSessionAbort (Session
);
766 // All attempts configured for this driver instance are not valid.
768 if (Private
->Session
== NULL
) {
769 Status
= gBS
->UninstallProtocolInterface (
770 Private
->ExtScsiPassThruHandle
,
771 &gEfiExtScsiPassThruProtocolGuid
,
772 &Private
->IScsiExtScsiPassThru
774 ASSERT_EFI_ERROR (Status
);
775 Private
->ExtScsiPassThruHandle
= NULL
;
778 // Reinstall the original ExtScsiPassThru back.
780 if (mPrivate
->OneSessionEstablished
&& ExistPrivate
!= NULL
) {
781 Status
= gBS
->InstallProtocolInterface (
782 &ExistPrivate
->ExtScsiPassThruHandle
,
783 &gEfiExtScsiPassThruProtocolGuid
,
784 EFI_NATIVE_INTERFACE
,
785 &ExistPrivate
->IScsiExtScsiPassThru
787 if (EFI_ERROR (Status
)) {
794 Status
= EFI_NOT_FOUND
;
801 // More than one attempt successes.
803 if (Private
->Session
!= NULL
&& mPrivate
->OneSessionEstablished
) {
805 AttemptConfigOrder
= IScsiGetVariableAndSize (
808 &AttemptConfigOrderSize
810 if (AttemptConfigOrder
== NULL
) {
813 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
814 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
||
815 AttemptConfigOrder
[Index
] == BootSelected
) {
820 if (mPrivate
->EnableMpio
) {
822 // Use the attempt in earlier order. Abort the later one in MPIO.
824 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
825 IScsiSessionAbort (Private
->Session
);
826 FreePool (Private
->Session
);
827 Private
->Session
= NULL
;
828 gBS
->UninstallProtocolInterface (
829 Private
->ExtScsiPassThruHandle
,
830 &gEfiExtScsiPassThruProtocolGuid
,
831 &Private
->IScsiExtScsiPassThru
833 Private
->ExtScsiPassThruHandle
= NULL
;
836 // Reinstall the original ExtScsiPassThru back.
838 Status
= gBS
->InstallProtocolInterface (
839 &ExistPrivate
->ExtScsiPassThruHandle
,
840 &gEfiExtScsiPassThruProtocolGuid
,
841 EFI_NATIVE_INTERFACE
,
842 &ExistPrivate
->IScsiExtScsiPassThru
844 if (EFI_ERROR (Status
)) {
850 if (AttemptConfigOrder
[Index
] != BootSelected
) {
853 mPrivate
->BootSelectedIndex
= BootSelected
;
855 // Clear the resource in ExistPrivate.
857 gBS
->UninstallProtocolInterface (
858 ExistPrivate
->Controller
,
860 &ExistPrivate
->IScsiIdentifier
863 IScsiRemoveNic (ExistPrivate
->Controller
);
864 if (ExistPrivate
->Session
!= NULL
) {
865 IScsiSessionAbort (ExistPrivate
->Session
);
868 if (ExistPrivate
->DevicePath
!= NULL
) {
869 Status
= gBS
->UninstallProtocolInterface (
870 ExistPrivate
->ExtScsiPassThruHandle
,
871 &gEfiDevicePathProtocolGuid
,
872 ExistPrivate
->DevicePath
874 if (EFI_ERROR (Status
)) {
878 FreePool (ExistPrivate
->DevicePath
);
881 gBS
->CloseEvent (ExistPrivate
->ExitBootServiceEvent
);
882 FreePool (ExistPrivate
);
887 // Use the attempt in earlier order as boot selected in single path mode.
889 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
897 mPrivate
->OneSessionEstablished
= TRUE
;
898 mPrivate
->BootSelectedIndex
= BootSelected
;
902 // Duplicate the Session's tcp connection device path. The source port field
903 // will be set to zero as one iSCSI session is comprised of several iSCSI
906 Private
->DevicePath
= IScsiGetTcpConnDevicePath (Private
->Session
);
907 if (Private
->DevicePath
== NULL
) {
908 Status
= EFI_DEVICE_ERROR
;
912 // Install the updated device path onto the ExtScsiPassThruHandle.
914 Status
= gBS
->InstallProtocolInterface (
915 &Private
->ExtScsiPassThruHandle
,
916 &gEfiDevicePathProtocolGuid
,
917 EFI_NATIVE_INTERFACE
,
920 if (EFI_ERROR (Status
)) {
925 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
927 Status
= gBS
->OpenProtocol (
928 Private
->ChildHandle
, /// Default Tcp child
932 Private
->ExtScsiPassThruHandle
,
933 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
935 if (EFI_ERROR (Status
)) {
936 gBS
->UninstallMultipleProtocolInterfaces (
937 Private
->ExtScsiPassThruHandle
,
938 &gEfiExtScsiPassThruProtocolGuid
,
939 &Private
->IScsiExtScsiPassThru
,
940 &gEfiDevicePathProtocolGuid
,
951 // Update/Publish the iSCSI Boot Firmware Table.
953 if (mPrivate
->BootSelectedIndex
!= 0) {
961 if (Private
->Session
!= NULL
) {
962 IScsiSessionAbort (Private
->Session
);
969 Stops a device controller or a bus controller. This is the worker function for
970 IScsiIp4(6)DriverBindingStop.
972 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
973 @param[in] ControllerHandle A handle to the device being stopped. The handle must
974 support a bus specific I/O protocol for the driver
975 to use to stop the device.
976 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
977 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
978 if NumberOfChildren is 0.
979 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
981 @retval EFI_SUCCESS The device was stopped.
982 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
983 @retval EFI_INVALID_PARAMETER Child handle is NULL.
984 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
985 because its interfaces are being used.
991 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
992 IN EFI_HANDLE ControllerHandle
,
993 IN UINTN NumberOfChildren
,
994 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
,
998 EFI_HANDLE IScsiController
;
1000 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
1001 ISCSI_DRIVER_DATA
*Private
;
1002 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
1003 ISCSI_CONNECTION
*Conn
;
1004 EFI_GUID
*ProtocolGuid
;
1005 EFI_GUID
*TcpServiceBindingGuid
;
1006 EFI_GUID
*TcpProtocolGuid
;
1009 if (NumberOfChildren
!= 0) {
1011 // We should have only one child.
1013 Status
= gBS
->OpenProtocol (
1014 ChildHandleBuffer
[0],
1015 &gEfiExtScsiPassThruProtocolGuid
,
1016 (VOID
**) &PassThru
,
1017 This
->DriverBindingHandle
,
1019 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1021 if (EFI_ERROR (Status
)) {
1022 return EFI_DEVICE_ERROR
;
1025 Private
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru
);
1026 Conn
= NET_LIST_HEAD (&Private
->Session
->Conns
, ISCSI_CONNECTION
, Link
);
1029 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
1030 // the protocol here, but do not uninstall the device path protocol and
1031 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
1033 if (IpVersion
== IP_VERSION_4
) {
1034 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1036 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1039 gBS
->CloseProtocol (
1040 Private
->ChildHandle
,
1043 Private
->ExtScsiPassThruHandle
1046 gBS
->CloseProtocol (
1050 Private
->ExtScsiPassThruHandle
1057 // Get the handle of the controller we are controling.
1059 if (IpVersion
== IP_VERSION_4
) {
1060 ProtocolGuid
= &gIScsiV4PrivateGuid
;
1061 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1062 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
1064 ProtocolGuid
= &gIScsiV6PrivateGuid
;
1065 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1066 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
1068 IScsiController
= NetLibGetNicHandle (ControllerHandle
, TcpProtocolGuid
);
1069 if (IScsiController
== NULL
) {
1073 Status
= gBS
->OpenProtocol (
1076 (VOID
**) &IScsiIdentifier
,
1077 This
->DriverBindingHandle
,
1079 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1081 if (EFI_ERROR (Status
)) {
1082 return EFI_DEVICE_ERROR
;
1085 Private
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
1086 ASSERT (Private
!= NULL
);
1088 if (Private
->ChildHandle
!= NULL
) {
1089 Status
= gBS
->CloseProtocol (
1090 Private
->ChildHandle
,
1092 This
->DriverBindingHandle
,
1096 ASSERT (!EFI_ERROR (Status
));
1098 Status
= NetLibDestroyServiceChild (
1100 This
->DriverBindingHandle
,
1101 TcpServiceBindingGuid
,
1102 Private
->ChildHandle
1105 ASSERT (!EFI_ERROR (Status
));
1108 gBS
->UninstallProtocolInterface (
1111 &Private
->IScsiIdentifier
1117 IScsiRemoveNic (IScsiController
);
1120 // Update the iSCSI Boot Firware Table.
1122 IScsiPublishIbft ();
1124 if (Private
->Session
!= NULL
) {
1125 IScsiSessionAbort (Private
->Session
);
1128 Status
= IScsiCleanDriverData (Private
);
1130 if (EFI_ERROR (Status
)) {
1138 Tests to see if this driver supports a given controller. If a child device is provided,
1139 it tests to see if this driver supports creating a handle for the specified child device.
1141 This function checks to see if the driver specified by This supports the device specified by
1142 ControllerHandle. Drivers typically use the device path attached to
1143 ControllerHandle and/or the services from the bus I/O abstraction attached to
1144 ControllerHandle to determine if the driver supports ControllerHandle. This function
1145 may be called many times during platform initialization. In order to reduce boot times, the tests
1146 performed by this function must be very small and take as little time as possible to execute. This
1147 function must not change the state of any hardware devices, and this function must be aware that the
1148 device specified by ControllerHandle may already be managed by the same driver or a
1149 different driver. This function must match its calls to AllocatePages() with FreePages(),
1150 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1151 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1152 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1153 to guarantee the state of ControllerHandle is not modified by this function.
1155 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1156 @param[in] ControllerHandle The handle of the controller to test. This handle
1157 must support a protocol interface that supplies
1158 an I/O abstraction to the driver.
1159 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1160 parameter is ignored by device drivers, and is optional for bus
1161 drivers. For bus drivers, if this parameter is not NULL, then
1162 the bus driver must determine if the bus controller specified
1163 by ControllerHandle and the child controller specified
1164 by RemainingDevicePath are both supported by this
1167 @retval EFI_SUCCESS The device specified by ControllerHandle and
1168 RemainingDevicePath is supported by the driver specified by This.
1169 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1170 RemainingDevicePath is already managed by the driver
1172 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1173 RemainingDevicePath is already managed by a different
1174 driver or an application that requires exclusive access.
1175 Currently not implemented.
1176 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1177 RemainingDevicePath is not supported by the driver specified by This.
1181 IScsiIp4DriverBindingSupported (
1182 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1183 IN EFI_HANDLE ControllerHandle
,
1184 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1187 return IScsiSupported (
1190 RemainingDevicePath
,
1196 Starts a device controller or a bus controller.
1198 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1199 As a result, much of the error checking on the parameters to Start() has been moved into this
1200 common boot service. It is legal to call Start() from other locations,
1201 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1202 1. ControllerHandle must be a valid EFI_HANDLE.
1203 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1204 EFI_DEVICE_PATH_PROTOCOL.
1205 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1206 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1208 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1209 @param[in] ControllerHandle The handle of the controller to start. This handle
1210 must support a protocol interface that supplies
1211 an I/O abstraction to the driver.
1212 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1213 parameter is ignored by device drivers, and is optional for bus
1214 drivers. For a bus driver, if this parameter is NULL, then handles
1215 for all the children of Controller are created by this driver.
1216 If this parameter is not NULL and the first Device Path Node is
1217 not the End of Device Path Node, then only the handle for the
1218 child device specified by the first Device Path Node of
1219 RemainingDevicePath is created by this driver.
1220 If the first Device Path Node of RemainingDevicePath is
1221 the End of Device Path Node, no child handle is created by this
1224 @retval EFI_SUCCESS The device was started.
1225 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1226 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1227 @retval Others The driver failed to start the device.
1232 IScsiIp4DriverBindingStart (
1233 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1234 IN EFI_HANDLE ControllerHandle
,
1235 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1240 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_4
);
1241 if (Status
== EFI_ALREADY_STARTED
) {
1242 Status
= EFI_SUCCESS
;
1249 Stops a device controller or a bus controller.
1251 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1252 As a result, much of the error checking on the parameters to Stop() has been moved
1253 into this common boot service. It is legal to call Stop() from other locations,
1254 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1255 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1256 same driver's Start() function.
1257 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1258 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1259 Start() function, and the Start() function must have called OpenProtocol() on
1260 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1262 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1263 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1264 support a bus specific I/O protocol for the driver
1265 to use to stop the device.
1266 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1267 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1268 if NumberOfChildren is 0.
1270 @retval EFI_SUCCESS The device was stopped.
1271 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1276 IScsiIp4DriverBindingStop (
1277 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1278 IN EFI_HANDLE ControllerHandle
,
1279 IN UINTN NumberOfChildren
,
1280 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1293 Tests to see if this driver supports a given controller. If a child device is provided,
1294 it tests to see if this driver supports creating a handle for the specified child device.
1296 This function checks to see if the driver specified by This supports the device specified by
1297 ControllerHandle. Drivers typically use the device path attached to
1298 ControllerHandle and/or the services from the bus I/O abstraction attached to
1299 ControllerHandle to determine if the driver supports ControllerHandle. This function
1300 may be called many times during platform initialization. In order to reduce boot times, the tests
1301 performed by this function must be very small and take as little time as possible to execute. This
1302 function must not change the state of any hardware devices, and this function must be aware that the
1303 device specified by ControllerHandle may already be managed by the same driver or a
1304 different driver. This function must match its calls to AllocatePages() with FreePages(),
1305 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1306 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1307 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1308 to guarantee the state of ControllerHandle is not modified by this function.
1310 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1311 @param[in] ControllerHandle The handle of the controller to test. This handle
1312 must support a protocol interface that supplies
1313 an I/O abstraction to the driver.
1314 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1315 parameter is ignored by device drivers, and is optional for bus
1316 drivers. For bus drivers, if this parameter is not NULL, then
1317 the bus driver must determine if the bus controller specified
1318 by ControllerHandle and the child controller specified
1319 by RemainingDevicePath are both supported by this
1322 @retval EFI_SUCCESS The device specified by ControllerHandle and
1323 RemainingDevicePath is supported by the driver specified by This.
1324 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1325 RemainingDevicePath is already managed by the driver
1327 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1328 RemainingDevicePath is already managed by a different
1329 driver or an application that requires exclusive access.
1330 Currently not implemented.
1331 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1332 RemainingDevicePath is not supported by the driver specified by This.
1336 IScsiIp6DriverBindingSupported (
1337 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1338 IN EFI_HANDLE ControllerHandle
,
1339 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1342 return IScsiSupported (
1345 RemainingDevicePath
,
1351 Starts a device controller or a bus controller.
1353 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1354 As a result, much of the error checking on the parameters to Start() has been moved into this
1355 common boot service. It is legal to call Start() from other locations,
1356 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1357 1. ControllerHandle must be a valid EFI_HANDLE.
1358 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1359 EFI_DEVICE_PATH_PROTOCOL.
1360 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1361 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1363 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1364 @param[in] ControllerHandle The handle of the controller to start. This handle
1365 must support a protocol interface that supplies
1366 an I/O abstraction to the driver.
1367 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1368 parameter is ignored by device drivers, and is optional for bus
1369 drivers. For a bus driver, if this parameter is NULL, then handles
1370 for all the children of Controller are created by this driver.
1371 If this parameter is not NULL and the first Device Path Node is
1372 not the End of Device Path Node, then only the handle for the
1373 child device specified by the first Device Path Node of
1374 RemainingDevicePath is created by this driver.
1375 If the first Device Path Node of RemainingDevicePath is
1376 the End of Device Path Node, no child handle is created by this
1379 @retval EFI_SUCCESS The device was started.
1380 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1381 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1382 @retval Others The driver failed to start the device.
1387 IScsiIp6DriverBindingStart (
1388 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1389 IN EFI_HANDLE ControllerHandle
,
1390 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1395 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_6
);
1396 if (Status
== EFI_ALREADY_STARTED
) {
1397 Status
= EFI_SUCCESS
;
1404 Stops a device controller or a bus controller.
1406 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1407 As a result, much of the error checking on the parameters to Stop() has been moved
1408 into this common boot service. It is legal to call Stop() from other locations,
1409 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1410 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1411 same driver's Start() function.
1412 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1413 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1414 Start() function, and the Start() function must have called OpenProtocol() on
1415 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1417 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1418 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1419 support a bus specific I/O protocol for the driver
1420 to use to stop the device.
1421 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1422 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1423 if NumberOfChildren is 0.
1425 @retval EFI_SUCCESS The device was stopped.
1426 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1431 IScsiIp6DriverBindingStop (
1432 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1433 IN EFI_HANDLE ControllerHandle
,
1434 IN UINTN NumberOfChildren
,
1435 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1448 Unload the iSCSI driver.
1450 @param[in] ImageHandle The handle of the driver image.
1452 @retval EFI_SUCCESS The driver is unloaded.
1453 @retval EFI_DEVICE_ERROR An unexpected error occurred.
1459 IN EFI_HANDLE ImageHandle
1463 UINTN DeviceHandleCount
;
1464 EFI_HANDLE
*DeviceHandleBuffer
;
1466 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1467 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1470 // Try to disonnect the driver from the devices it's controlling.
1472 Status
= gBS
->LocateHandleBuffer (
1479 if (EFI_ERROR (Status
)) {
1484 // Disconnect the iSCSI4 driver from the controlled device.
1486 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1487 Status
= IScsiTestManagedDevice (
1488 DeviceHandleBuffer
[Index
],
1489 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1490 &gEfiTcp4ProtocolGuid
)
1492 if (EFI_ERROR (Status
)) {
1495 Status
= gBS
->DisconnectController (
1496 DeviceHandleBuffer
[Index
],
1497 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1500 if (EFI_ERROR (Status
)) {
1506 // Disconnect the iSCSI6 driver from the controlled device.
1508 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1509 Status
= IScsiTestManagedDevice (
1510 DeviceHandleBuffer
[Index
],
1511 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1512 &gEfiTcp6ProtocolGuid
1514 if (EFI_ERROR (Status
)) {
1517 Status
= gBS
->DisconnectController (
1518 DeviceHandleBuffer
[Index
],
1519 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1522 if (EFI_ERROR (Status
)) {
1528 // Unload the iSCSI configuration form.
1530 Status
= IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1531 if (EFI_ERROR (Status
)) {
1536 // Uninstall the protocols installed by iSCSI driver.
1538 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1540 &gEfiAuthenticationInfoProtocolGuid
,
1541 &gIScsiAuthenticationInfo
,
1544 if (EFI_ERROR (Status
)) {
1548 if (gIScsiControllerNameTable
!= NULL
) {
1549 Status
= FreeUnicodeStringTable (gIScsiControllerNameTable
);
1550 if (EFI_ERROR (Status
)) {
1553 gIScsiControllerNameTable
= NULL
;
1557 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
1558 // if it has been installed.
1560 Status
= gBS
->HandleProtocol (
1561 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1562 &gEfiComponentNameProtocolGuid
,
1563 (VOID
**) &ComponentName
1565 if (!EFI_ERROR (Status
)) {
1566 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1567 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1568 &gEfiComponentNameProtocolGuid
,
1572 if (EFI_ERROR (Status
)) {
1577 Status
= gBS
->HandleProtocol (
1578 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1579 &gEfiComponentName2ProtocolGuid
,
1580 (VOID
**) &ComponentName2
1582 if (!EFI_ERROR (Status
)) {
1583 gBS
->UninstallMultipleProtocolInterfaces (
1584 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1585 &gEfiComponentName2ProtocolGuid
,
1589 if (EFI_ERROR (Status
)) {
1595 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
1596 // if it has been installed.
1598 Status
= gBS
->HandleProtocol (
1599 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1600 &gEfiComponentNameProtocolGuid
,
1601 (VOID
**) &ComponentName
1603 if (!EFI_ERROR (Status
)) {
1604 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1605 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1606 &gEfiComponentNameProtocolGuid
,
1610 if (EFI_ERROR (Status
)) {
1615 Status
= gBS
->HandleProtocol (
1616 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1617 &gEfiComponentName2ProtocolGuid
,
1618 (VOID
**) &ComponentName2
1620 if (!EFI_ERROR (Status
)) {
1621 gBS
->UninstallMultipleProtocolInterfaces (
1622 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1623 &gEfiComponentName2ProtocolGuid
,
1627 if (EFI_ERROR (Status
)) {
1633 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
1635 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1636 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1637 &gEfiDriverBindingProtocolGuid
,
1638 &gIScsiIp4DriverBinding
,
1639 &gEfiIScsiInitiatorNameProtocolGuid
,
1640 &gIScsiInitiatorName
,
1643 if (EFI_ERROR (Status
)) {
1647 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1648 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1649 &gEfiDriverBindingProtocolGuid
,
1650 &gIScsiIp6DriverBinding
,
1656 if (DeviceHandleBuffer
!= NULL
) {
1657 FreePool (DeviceHandleBuffer
);
1664 This is the declaration of an EFI image entry point. This entry point is
1665 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1666 both device drivers and bus drivers.
1668 The entry point for iSCSI driver which initializes the global variables and
1669 installs the driver binding, component name protocol, iSCSI initiator name
1670 protocol and Authentication Info protocol on its image.
1672 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1673 @param[in] SystemTable A pointer to the EFI System Table.
1675 @retval EFI_SUCCESS The operation completed successfully.
1676 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1681 IScsiDriverEntryPoint (
1682 IN EFI_HANDLE ImageHandle
,
1683 IN EFI_SYSTEM_TABLE
*SystemTable
1687 EFI_ISCSI_INITIATOR_NAME_PROTOCOL
*IScsiInitiatorName
;
1688 EFI_AUTHENTICATION_INFO_PROTOCOL
*AuthenticationInfo
;
1691 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
1693 Status
= gBS
->LocateProtocol (
1694 &gEfiIScsiInitiatorNameProtocolGuid
,
1696 (VOID
**) &IScsiInitiatorName
1698 if (!EFI_ERROR (Status
)) {
1699 return EFI_ACCESS_DENIED
;
1703 // Initialize the EFI Driver Library.
1705 Status
= EfiLibInstallDriverBindingComponentName2 (
1708 &gIScsiIp4DriverBinding
,
1710 &gIScsiComponentName
,
1711 &gIScsiComponentName2
1713 if (EFI_ERROR (Status
)) {
1717 Status
= EfiLibInstallDriverBindingComponentName2 (
1720 &gIScsiIp6DriverBinding
,
1722 &gIScsiComponentName
,
1723 &gIScsiComponentName2
1725 if (EFI_ERROR (Status
)) {
1730 // Install the iSCSI Initiator Name Protocol.
1732 Status
= gBS
->InstallProtocolInterface (
1734 &gEfiIScsiInitiatorNameProtocolGuid
,
1735 EFI_NATIVE_INTERFACE
,
1736 &gIScsiInitiatorName
1738 if (EFI_ERROR (Status
)) {
1743 // Create the private data structures.
1745 mPrivate
= AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA
));
1746 if (mPrivate
== NULL
) {
1747 Status
= EFI_OUT_OF_RESOURCES
;
1751 InitializeListHead (&mPrivate
->NicInfoList
);
1752 InitializeListHead (&mPrivate
->AttemptConfigs
);
1755 // Initialize the configuration form of iSCSI.
1757 Status
= IScsiConfigFormInit (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1758 if (EFI_ERROR (Status
)) {
1763 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
1764 // do not produce the protocol instance.
1766 Status
= gBS
->LocateProtocol (
1767 &gEfiAuthenticationInfoProtocolGuid
,
1769 (VOID
**) &AuthenticationInfo
1771 if (Status
== EFI_NOT_FOUND
) {
1772 Status
= gBS
->InstallProtocolInterface (
1774 &gEfiAuthenticationInfoProtocolGuid
,
1775 EFI_NATIVE_INTERFACE
,
1776 &gIScsiAuthenticationInfo
1778 if (EFI_ERROR (Status
)) {
1786 IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1789 FreePool (mPrivate
);
1792 gBS
->UninstallMultipleProtocolInterfaces (
1794 &gEfiIScsiInitiatorNameProtocolGuid
,
1795 &gIScsiInitiatorName
,
1800 gBS
->UninstallMultipleProtocolInterfaces (
1801 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1802 &gEfiDriverBindingProtocolGuid
,
1803 &gIScsiIp6DriverBinding
,
1804 &gEfiComponentName2ProtocolGuid
,
1805 &gIScsiComponentName2
,
1806 &gEfiComponentNameProtocolGuid
,
1807 &gIScsiComponentName
,
1812 gBS
->UninstallMultipleProtocolInterfaces (
1814 &gEfiDriverBindingProtocolGuid
,
1815 &gIScsiIp4DriverBinding
,
1816 &gEfiComponentName2ProtocolGuid
,
1817 &gIScsiComponentName2
,
1818 &gEfiComponentNameProtocolGuid
,
1819 &gIScsiComponentName
,