2 The entry point of IScsi driver.
4 Copyright (c) 2004 - 2017, 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
;
255 EFI_GUID
*DnsServiceBindingGuid
;
257 if (IpVersion
== IP_VERSION_4
) {
258 IScsiServiceBindingGuid
= &gIScsiV4PrivateGuid
;
259 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
260 DhcpServiceBindingGuid
= &gEfiDhcp4ServiceBindingProtocolGuid
;
261 DnsServiceBindingGuid
= &gEfiDns4ServiceBindingProtocolGuid
;
264 IScsiServiceBindingGuid
= &gIScsiV6PrivateGuid
;
265 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
266 DhcpServiceBindingGuid
= &gEfiDhcp6ServiceBindingProtocolGuid
;
267 DnsServiceBindingGuid
= &gEfiDns6ServiceBindingProtocolGuid
;
270 Status
= gBS
->OpenProtocol (
272 IScsiServiceBindingGuid
,
274 This
->DriverBindingHandle
,
276 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
278 if (!EFI_ERROR (Status
)) {
279 return EFI_ALREADY_STARTED
;
282 Status
= gBS
->OpenProtocol (
284 TcpServiceBindingGuid
,
286 This
->DriverBindingHandle
,
288 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
290 if (EFI_ERROR (Status
)) {
291 return EFI_UNSUPPORTED
;
294 Status
= IScsiIsDevicePathSupported (RemainingDevicePath
);
295 if (EFI_ERROR (Status
)) {
296 return EFI_UNSUPPORTED
;
299 if (IScsiDhcpIsConfigured (ControllerHandle
, IpVersion
)) {
300 Status
= gBS
->OpenProtocol (
302 DhcpServiceBindingGuid
,
304 This
->DriverBindingHandle
,
306 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
308 if (EFI_ERROR (Status
)) {
309 return EFI_UNSUPPORTED
;
313 if (IScsiDnsIsConfigured (ControllerHandle
)) {
314 Status
= gBS
->OpenProtocol (
316 DnsServiceBindingGuid
,
318 This
->DriverBindingHandle
,
320 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
322 if (EFI_ERROR (Status
)) {
323 return EFI_UNSUPPORTED
;
332 Start to manage the controller. This is the worker function for
333 IScsiIp4(6)DriverBindingStart.
335 @param[in] Image Handle of the image.
336 @param[in] ControllerHandle Handle of the controller.
337 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
339 @retval EFI_SUCCES This driver was started.
340 @retval EFI_ALREADY_STARTED This driver is already running on this device.
341 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
342 @retval EFI_NOT_FOUND There is no sufficient information to establish
344 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
345 @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
346 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
347 because its interfaces are being used.
353 IN EFI_HANDLE ControllerHandle
,
358 ISCSI_DRIVER_DATA
*Private
;
360 LIST_ENTRY
*NextEntry
;
361 ISCSI_ATTEMPT_CONFIG_NVDATA
*AttemptConfigData
;
362 ISCSI_SESSION
*Session
;
364 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*ExistIScsiExtScsiPassThru
;
365 ISCSI_DRIVER_DATA
*ExistPrivate
;
366 UINT8
*AttemptConfigOrder
;
367 UINTN AttemptConfigOrderSize
;
369 EFI_HANDLE
*HandleBuffer
;
370 UINTN NumberOfHandles
;
371 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
372 EFI_GUID
*IScsiPrivateGuid
;
373 EFI_GUID
*TcpServiceBindingGuid
;
374 CHAR16 MacString
[ISCSI_MAX_MAC_STRING_LEN
];
377 EFI_GUID
*ProtocolGuid
;
378 UINT8 NetworkBootPolicy
;
379 ISCSI_SESSION_CONFIG_NVDATA
*NvData
;
382 // Test to see if iSCSI driver supports the given controller.
385 if (IpVersion
== IP_VERSION_4
) {
386 IScsiPrivateGuid
= &gIScsiV4PrivateGuid
;
387 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
388 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
389 } else if (IpVersion
== IP_VERSION_6
) {
390 IScsiPrivateGuid
= &gIScsiV6PrivateGuid
;
391 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
392 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
394 return EFI_INVALID_PARAMETER
;
397 Status
= gBS
->OpenProtocol (
403 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
405 if (!EFI_ERROR (Status
)) {
406 return EFI_ALREADY_STARTED
;
409 Status
= gBS
->OpenProtocol (
411 TcpServiceBindingGuid
,
415 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
417 if (EFI_ERROR (Status
)) {
418 return EFI_UNSUPPORTED
;
421 NetworkBootPolicy
= PcdGet8 (PcdIScsiAIPNetworkBootPolicy
);
422 if (NetworkBootPolicy
!= ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_AIP
) {
424 // Check existing iSCSI AIP.
426 Status
= IScsiCheckAip ();
427 if (!EFI_ERROR (Status
)) {
429 // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
436 // Record the incoming NIC info.
438 Status
= IScsiAddNic (ControllerHandle
);
439 if (EFI_ERROR (Status
)) {
444 // Create the instance private data.
446 Private
= IScsiCreateDriverData (Image
, ControllerHandle
);
447 if (Private
== NULL
) {
448 return EFI_OUT_OF_RESOURCES
;
452 // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
453 // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
454 // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
455 // IScsiDriverBindingStop() will be called.
457 Status
= NetLibCreateServiceChild (
460 TcpServiceBindingGuid
,
461 &Private
->ChildHandle
464 if (EFI_ERROR (Status
)) {
468 Status
= gBS
->OpenProtocol (
469 Private
->ChildHandle
, /// Default Tcp child
474 EFI_OPEN_PROTOCOL_BY_DRIVER
477 if (EFI_ERROR (Status
)) {
482 // Always install private protocol no matter what happens later. We need to
483 // keep the relationship between ControllerHandle and ChildHandle.
485 Status
= gBS
->InstallProtocolInterface (
488 EFI_NATIVE_INTERFACE
,
489 &Private
->IScsiIdentifier
491 if (EFI_ERROR (Status
)) {
495 if (IpVersion
== IP_VERSION_4
) {
496 mPrivate
->Ipv6Flag
= FALSE
;
498 mPrivate
->Ipv6Flag
= TRUE
;
502 // Get the current iSCSI configuration data.
504 Status
= IScsiGetConfigData (Private
);
505 if (EFI_ERROR (Status
)) {
510 // If there is already a successul attempt, check whether this attempt is the
511 // first "enabled for MPIO" attempt. If not, still try the first attempt.
512 // In single path mode, try all attempts.
515 Status
= EFI_NOT_FOUND
;
517 if (mPrivate
->OneSessionEstablished
&& mPrivate
->EnableMpio
) {
518 AttemptConfigData
= NULL
;
519 NET_LIST_FOR_EACH (Entry
, &mPrivate
->AttemptConfigs
) {
520 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
521 if (AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_ENABLED_FOR_MPIO
) {
526 if (AttemptConfigData
== NULL
) {
530 if (AttemptConfigData
->AttemptConfigIndex
== mPrivate
->BootSelectedIndex
) {
535 // Uninstall the original ExtScsiPassThru first.
539 // Locate all ExtScsiPassThru protocol instances.
541 Status
= gBS
->LocateHandleBuffer (
543 &gEfiExtScsiPassThruProtocolGuid
,
548 if (EFI_ERROR (Status
)) {
553 // Find ExtScsiPassThru protocol instance produced by this driver.
555 ExistIScsiExtScsiPassThru
= NULL
;
556 for (Index
= 0; Index
< NumberOfHandles
&& ExistIScsiExtScsiPassThru
== NULL
; Index
++) {
557 Status
= gBS
->HandleProtocol (
559 &gEfiDevicePathProtocolGuid
,
560 (VOID
**) &DevicePath
562 if (EFI_ERROR (Status
)) {
566 while (!IsDevicePathEnd (DevicePath
)) {
567 if ((DevicePath
->Type
== MESSAGING_DEVICE_PATH
) && (DevicePath
->SubType
== MSG_MAC_ADDR_DP
)) {
569 // Get the ExtScsiPassThru protocol instance.
571 Status
= gBS
->HandleProtocol (
573 &gEfiExtScsiPassThruProtocolGuid
,
574 (VOID
**) &ExistIScsiExtScsiPassThru
576 ASSERT_EFI_ERROR (Status
);
580 DevicePath
= NextDevicePathNode (DevicePath
);
584 FreePool (HandleBuffer
);
586 if (ExistIScsiExtScsiPassThru
== NULL
) {
587 Status
= EFI_NOT_FOUND
;
591 ExistPrivate
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru
);
593 Status
= gBS
->UninstallProtocolInterface (
594 ExistPrivate
->ExtScsiPassThruHandle
,
595 &gEfiExtScsiPassThruProtocolGuid
,
596 &ExistPrivate
->IScsiExtScsiPassThru
598 if (EFI_ERROR (Status
)) {
604 // Install the Ext SCSI PASS THRU protocol.
606 Status
= gBS
->InstallProtocolInterface (
607 &Private
->ExtScsiPassThruHandle
,
608 &gEfiExtScsiPassThruProtocolGuid
,
609 EFI_NATIVE_INTERFACE
,
610 &Private
->IScsiExtScsiPassThru
612 if (EFI_ERROR (Status
)) {
618 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &mPrivate
->AttemptConfigs
) {
619 AttemptConfigData
= NET_LIST_USER_STRUCT (Entry
, ISCSI_ATTEMPT_CONFIG_NVDATA
, Link
);
621 // Don't process the attempt that does not associate with the current NIC or
622 // this attempt is disabled or established.
624 if (AttemptConfigData
->NicIndex
!= mPrivate
->CurrentNic
||
625 AttemptConfigData
->SessionConfigData
.Enabled
== ISCSI_DISABLED
||
626 AttemptConfigData
->ValidPath
) {
631 // In multipath mode, don't process attempts configured for single path.
632 // In default single path mode, don't process attempts configured for multipath.
634 if ((mPrivate
->EnableMpio
&&
635 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED_FOR_MPIO
) ||
636 (!mPrivate
->EnableMpio
&&
637 AttemptConfigData
->SessionConfigData
.Enabled
!= ISCSI_ENABLED
)) {
642 // Don't process the attempt that fails to get the init/target information from DHCP.
644 if (AttemptConfigData
->SessionConfigData
.InitiatorInfoFromDhcp
&&
645 !AttemptConfigData
->DhcpSuccess
) {
646 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
647 mPrivate
->ValidSinglePathCount
--;
653 // Don't process the autoconfigure path if it is already established.
655 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
656 AttemptConfigData
->AutoConfigureSuccess
) {
661 // Don't process the attempt if its IP mode is not in the current IP version.
663 if (!mPrivate
->Ipv6Flag
) {
664 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP6
) {
667 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
668 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP6
) {
672 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_IP4
) {
675 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
&&
676 AttemptConfigData
->AutoConfigureMode
== IP_MODE_AUTOCONFIG_IP4
) {
682 // Fill in the Session and init it.
684 Session
= (ISCSI_SESSION
*) AllocateZeroPool (sizeof (ISCSI_SESSION
));
685 if (Session
== NULL
) {
686 Status
= EFI_OUT_OF_RESOURCES
;
690 Session
->Private
= Private
;
691 Session
->ConfigData
= AttemptConfigData
;
692 Session
->AuthType
= AttemptConfigData
->AuthenticationType
;
694 AsciiStrToUnicodeStrS (AttemptConfigData
->MacString
, MacString
, ARRAY_SIZE (MacString
));
696 mPrivate
->PortString
,
697 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
700 (UINTN
) AttemptConfigData
->AttemptConfigIndex
703 if (Session
->AuthType
== ISCSI_AUTH_TYPE_CHAP
) {
704 Session
->AuthData
.CHAP
.AuthConfig
= &AttemptConfigData
->AuthConfigData
.CHAP
;
707 IScsiSessionInit (Session
, FALSE
);
710 // Try to login and create an iSCSI session according to the configuration.
712 Status
= IScsiSessionLogin (Session
);
713 if (Status
== EFI_MEDIA_CHANGED
) {
715 // The specified target is not available, and the redirection information is
716 // received. Login the session again with the updated target address.
718 Status
= IScsiSessionLogin (Session
);
719 } else if (Status
== EFI_NOT_READY
) {
720 Status
= IScsiSessionReLogin (Session
);
724 // Restore the origial user setting which specifies the proxy/virtual iSCSI target to NV region.
726 NvData
= &AttemptConfigData
->SessionConfigData
;
727 if (NvData
->RedirectFlag
) {
728 NvData
->TargetPort
= NvData
->OriginalTargetPort
;
729 CopyMem (&NvData
->TargetIp
, &NvData
->OriginalTargetIp
, sizeof (EFI_IP_ADDRESS
));
730 NvData
->RedirectFlag
= FALSE
;
733 mPrivate
->PortString
,
734 &gEfiIScsiInitiatorNameProtocolGuid
,
735 ISCSI_CONFIG_VAR_ATTR
,
736 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
741 if (EFI_ERROR (Status
)) {
743 // In Single path mode, only the successful attempt will be recorded in iBFT;
744 // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
746 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
747 mPrivate
->ValidSinglePathCount
--;
753 AttemptConfigData
->ValidPath
= TRUE
;
756 // Do not record the attempt in iBFT if it login with KRB5.
757 // TODO: record KRB5 attempt information in the iSCSI device path.
759 if (Session
->AuthType
== ISCSI_AUTH_TYPE_KRB
) {
760 if (!mPrivate
->EnableMpio
&& mPrivate
->ValidSinglePathCount
> 0) {
761 mPrivate
->ValidSinglePathCount
--;
764 AttemptConfigData
->ValidiBFTPath
= FALSE
;
766 AttemptConfigData
->ValidiBFTPath
= TRUE
;
770 // IScsi session success. Update the attempt state to NVR.
772 if (AttemptConfigData
->SessionConfigData
.IpMode
== IP_MODE_AUTOCONFIG
) {
773 AttemptConfigData
->AutoConfigureSuccess
= TRUE
;
777 mPrivate
->PortString
,
778 &gEfiIScsiInitiatorNameProtocolGuid
,
779 ISCSI_CONFIG_VAR_ATTR
,
780 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA
),
785 // Select the first login session. Abort others.
787 if (Private
->Session
== NULL
) {
788 Private
->Session
= Session
;
789 BootSelected
= AttemptConfigData
->AttemptConfigIndex
;
791 // Don't validate other attempt in multipath mode if one is success.
793 if (mPrivate
->EnableMpio
) {
797 IScsiSessionAbort (Session
);
804 // All attempts configured for this driver instance are not valid.
806 if (Private
->Session
== NULL
) {
807 Status
= gBS
->UninstallProtocolInterface (
808 Private
->ExtScsiPassThruHandle
,
809 &gEfiExtScsiPassThruProtocolGuid
,
810 &Private
->IScsiExtScsiPassThru
812 ASSERT_EFI_ERROR (Status
);
813 Private
->ExtScsiPassThruHandle
= NULL
;
816 // Reinstall the original ExtScsiPassThru back.
818 if (mPrivate
->OneSessionEstablished
&& ExistPrivate
!= NULL
) {
819 Status
= gBS
->InstallProtocolInterface (
820 &ExistPrivate
->ExtScsiPassThruHandle
,
821 &gEfiExtScsiPassThruProtocolGuid
,
822 EFI_NATIVE_INTERFACE
,
823 &ExistPrivate
->IScsiExtScsiPassThru
825 if (EFI_ERROR (Status
)) {
832 Status
= EFI_NOT_FOUND
;
839 // More than one attempt successes.
841 if (Private
->Session
!= NULL
&& mPrivate
->OneSessionEstablished
) {
843 AttemptConfigOrder
= IScsiGetVariableAndSize (
846 &AttemptConfigOrderSize
848 if (AttemptConfigOrder
== NULL
) {
851 for (Index
= 0; Index
< AttemptConfigOrderSize
/ sizeof (UINT8
); Index
++) {
852 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
||
853 AttemptConfigOrder
[Index
] == BootSelected
) {
858 if (mPrivate
->EnableMpio
) {
860 // Use the attempt in earlier order. Abort the later one in MPIO.
862 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
863 IScsiSessionAbort (Private
->Session
);
864 FreePool (Private
->Session
);
865 Private
->Session
= NULL
;
866 gBS
->UninstallProtocolInterface (
867 Private
->ExtScsiPassThruHandle
,
868 &gEfiExtScsiPassThruProtocolGuid
,
869 &Private
->IScsiExtScsiPassThru
871 Private
->ExtScsiPassThruHandle
= NULL
;
874 // Reinstall the original ExtScsiPassThru back.
876 Status
= gBS
->InstallProtocolInterface (
877 &ExistPrivate
->ExtScsiPassThruHandle
,
878 &gEfiExtScsiPassThruProtocolGuid
,
879 EFI_NATIVE_INTERFACE
,
880 &ExistPrivate
->IScsiExtScsiPassThru
882 if (EFI_ERROR (Status
)) {
888 if (AttemptConfigOrder
[Index
] != BootSelected
) {
891 mPrivate
->BootSelectedIndex
= BootSelected
;
893 // Clear the resource in ExistPrivate.
895 gBS
->UninstallProtocolInterface (
896 ExistPrivate
->Controller
,
898 &ExistPrivate
->IScsiIdentifier
901 IScsiRemoveNic (ExistPrivate
->Controller
);
902 if (ExistPrivate
->Session
!= NULL
) {
903 IScsiSessionAbort (ExistPrivate
->Session
);
906 if (ExistPrivate
->DevicePath
!= NULL
) {
907 Status
= gBS
->UninstallProtocolInterface (
908 ExistPrivate
->ExtScsiPassThruHandle
,
909 &gEfiDevicePathProtocolGuid
,
910 ExistPrivate
->DevicePath
912 if (EFI_ERROR (Status
)) {
916 FreePool (ExistPrivate
->DevicePath
);
919 gBS
->CloseEvent (ExistPrivate
->ExitBootServiceEvent
);
920 FreePool (ExistPrivate
);
925 // Use the attempt in earlier order as boot selected in single path mode.
927 if (AttemptConfigOrder
[Index
] == mPrivate
->BootSelectedIndex
) {
935 mPrivate
->OneSessionEstablished
= TRUE
;
936 mPrivate
->BootSelectedIndex
= BootSelected
;
940 // Duplicate the Session's tcp connection device path. The source port field
941 // will be set to zero as one iSCSI session is comprised of several iSCSI
944 Private
->DevicePath
= IScsiGetTcpConnDevicePath (Private
->Session
);
945 if (Private
->DevicePath
== NULL
) {
946 Status
= EFI_DEVICE_ERROR
;
950 // Install the updated device path onto the ExtScsiPassThruHandle.
952 Status
= gBS
->InstallProtocolInterface (
953 &Private
->ExtScsiPassThruHandle
,
954 &gEfiDevicePathProtocolGuid
,
955 EFI_NATIVE_INTERFACE
,
958 if (EFI_ERROR (Status
)) {
963 // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
965 Status
= gBS
->OpenProtocol (
966 Private
->ChildHandle
, /// Default Tcp child
970 Private
->ExtScsiPassThruHandle
,
971 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
973 if (EFI_ERROR (Status
)) {
974 gBS
->UninstallMultipleProtocolInterfaces (
975 Private
->ExtScsiPassThruHandle
,
976 &gEfiExtScsiPassThruProtocolGuid
,
977 &Private
->IScsiExtScsiPassThru
,
978 &gEfiDevicePathProtocolGuid
,
989 // Update/Publish the iSCSI Boot Firmware Table.
991 if (mPrivate
->BootSelectedIndex
!= 0) {
999 if (Private
->Session
!= NULL
) {
1000 IScsiSessionAbort (Private
->Session
);
1007 Stops a device controller or a bus controller. This is the worker function for
1008 IScsiIp4(6)DriverBindingStop.
1010 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1011 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1012 support a bus specific I/O protocol for the driver
1013 to use to stop the device.
1014 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1015 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1016 if NumberOfChildren is 0.
1017 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1019 @retval EFI_SUCCESS The device was stopped.
1020 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1021 @retval EFI_INVALID_PARAMETER Child handle is NULL.
1022 @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
1023 because its interfaces are being used.
1029 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1030 IN EFI_HANDLE ControllerHandle
,
1031 IN UINTN NumberOfChildren
,
1032 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
,
1036 EFI_HANDLE IScsiController
;
1038 ISCSI_PRIVATE_PROTOCOL
*IScsiIdentifier
;
1039 ISCSI_DRIVER_DATA
*Private
;
1040 EFI_EXT_SCSI_PASS_THRU_PROTOCOL
*PassThru
;
1041 ISCSI_CONNECTION
*Conn
;
1042 EFI_GUID
*ProtocolGuid
;
1043 EFI_GUID
*TcpServiceBindingGuid
;
1044 EFI_GUID
*TcpProtocolGuid
;
1047 if (NumberOfChildren
!= 0) {
1049 // We should have only one child.
1051 Status
= gBS
->OpenProtocol (
1052 ChildHandleBuffer
[0],
1053 &gEfiExtScsiPassThruProtocolGuid
,
1054 (VOID
**) &PassThru
,
1055 This
->DriverBindingHandle
,
1057 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1059 if (EFI_ERROR (Status
)) {
1060 return EFI_DEVICE_ERROR
;
1063 Private
= ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru
);
1064 Conn
= NET_LIST_HEAD (&Private
->Session
->Conns
, ISCSI_CONNECTION
, Link
);
1067 // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
1068 // the protocol here, but do not uninstall the device path protocol and
1069 // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
1071 if (IpVersion
== IP_VERSION_4
) {
1072 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1074 ProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1077 gBS
->CloseProtocol (
1078 Private
->ChildHandle
,
1081 Private
->ExtScsiPassThruHandle
1084 gBS
->CloseProtocol (
1088 Private
->ExtScsiPassThruHandle
1095 // Get the handle of the controller we are controling.
1097 if (IpVersion
== IP_VERSION_4
) {
1098 ProtocolGuid
= &gIScsiV4PrivateGuid
;
1099 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
1100 TcpServiceBindingGuid
= &gEfiTcp4ServiceBindingProtocolGuid
;
1102 ProtocolGuid
= &gIScsiV6PrivateGuid
;
1103 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
1104 TcpServiceBindingGuid
= &gEfiTcp6ServiceBindingProtocolGuid
;
1106 IScsiController
= NetLibGetNicHandle (ControllerHandle
, TcpProtocolGuid
);
1107 if (IScsiController
== NULL
) {
1111 Status
= gBS
->OpenProtocol (
1114 (VOID
**) &IScsiIdentifier
,
1115 This
->DriverBindingHandle
,
1117 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1119 if (EFI_ERROR (Status
)) {
1120 return EFI_DEVICE_ERROR
;
1123 Private
= ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier
);
1124 ASSERT (Private
!= NULL
);
1126 if (Private
->ChildHandle
!= NULL
) {
1127 Status
= gBS
->CloseProtocol (
1128 Private
->ChildHandle
,
1130 This
->DriverBindingHandle
,
1134 ASSERT (!EFI_ERROR (Status
));
1136 Status
= NetLibDestroyServiceChild (
1138 This
->DriverBindingHandle
,
1139 TcpServiceBindingGuid
,
1140 Private
->ChildHandle
1143 ASSERT (!EFI_ERROR (Status
));
1146 gBS
->UninstallProtocolInterface (
1149 &Private
->IScsiIdentifier
1155 IScsiRemoveNic (IScsiController
);
1158 // Update the iSCSI Boot Firware Table.
1160 IScsiPublishIbft ();
1162 if (Private
->Session
!= NULL
) {
1163 IScsiSessionAbort (Private
->Session
);
1166 Status
= IScsiCleanDriverData (Private
);
1168 if (EFI_ERROR (Status
)) {
1176 Tests to see if this driver supports a given controller. If a child device is provided,
1177 it tests to see if this driver supports creating a handle for the specified child device.
1179 This function checks to see if the driver specified by This supports the device specified by
1180 ControllerHandle. Drivers typically use the device path attached to
1181 ControllerHandle and/or the services from the bus I/O abstraction attached to
1182 ControllerHandle to determine if the driver supports ControllerHandle. This function
1183 may be called many times during platform initialization. In order to reduce boot times, the tests
1184 performed by this function must be very small and take as little time as possible to execute. This
1185 function must not change the state of any hardware devices, and this function must be aware that the
1186 device specified by ControllerHandle may already be managed by the same driver or a
1187 different driver. This function must match its calls to AllocatePages() with FreePages(),
1188 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1189 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1190 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1191 to guarantee the state of ControllerHandle is not modified by this function.
1193 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1194 @param[in] ControllerHandle The handle of the controller to test. This handle
1195 must support a protocol interface that supplies
1196 an I/O abstraction to the driver.
1197 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1198 parameter is ignored by device drivers, and is optional for bus
1199 drivers. For bus drivers, if this parameter is not NULL, then
1200 the bus driver must determine if the bus controller specified
1201 by ControllerHandle and the child controller specified
1202 by RemainingDevicePath are both supported by this
1205 @retval EFI_SUCCESS The device specified by ControllerHandle and
1206 RemainingDevicePath is supported by the driver specified by This.
1207 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1208 RemainingDevicePath is already managed by the driver
1210 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1211 RemainingDevicePath is already managed by a different
1212 driver or an application that requires exclusive access.
1213 Currently not implemented.
1214 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1215 RemainingDevicePath is not supported by the driver specified by This.
1219 IScsiIp4DriverBindingSupported (
1220 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1221 IN EFI_HANDLE ControllerHandle
,
1222 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1225 return IScsiSupported (
1228 RemainingDevicePath
,
1234 Starts a device controller or a bus controller.
1236 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1237 As a result, much of the error checking on the parameters to Start() has been moved into this
1238 common boot service. It is legal to call Start() from other locations,
1239 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1240 1. ControllerHandle must be a valid EFI_HANDLE.
1241 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1242 EFI_DEVICE_PATH_PROTOCOL.
1243 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1244 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1246 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1247 @param[in] ControllerHandle The handle of the controller to start. This handle
1248 must support a protocol interface that supplies
1249 an I/O abstraction to the driver.
1250 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1251 parameter is ignored by device drivers, and is optional for bus
1252 drivers. For a bus driver, if this parameter is NULL, then handles
1253 for all the children of Controller are created by this driver.
1254 If this parameter is not NULL and the first Device Path Node is
1255 not the End of Device Path Node, then only the handle for the
1256 child device specified by the first Device Path Node of
1257 RemainingDevicePath is created by this driver.
1258 If the first Device Path Node of RemainingDevicePath is
1259 the End of Device Path Node, no child handle is created by this
1262 @retval EFI_SUCCESS The device was started.
1263 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1264 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1265 @retval Others The driver failed to start the device.
1270 IScsiIp4DriverBindingStart (
1271 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1272 IN EFI_HANDLE ControllerHandle
,
1273 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1278 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_4
);
1279 if (Status
== EFI_ALREADY_STARTED
) {
1280 Status
= EFI_SUCCESS
;
1287 Stops a device controller or a bus controller.
1289 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1290 As a result, much of the error checking on the parameters to Stop() has been moved
1291 into this common boot service. It is legal to call Stop() from other locations,
1292 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1293 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1294 same driver's Start() function.
1295 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1296 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1297 Start() function, and the Start() function must have called OpenProtocol() on
1298 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1300 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1301 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1302 support a bus specific I/O protocol for the driver
1303 to use to stop the device.
1304 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1305 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1306 if NumberOfChildren is 0.
1308 @retval EFI_SUCCESS The device was stopped.
1309 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1314 IScsiIp4DriverBindingStop (
1315 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1316 IN EFI_HANDLE ControllerHandle
,
1317 IN UINTN NumberOfChildren
,
1318 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1331 Tests to see if this driver supports a given controller. If a child device is provided,
1332 it tests to see if this driver supports creating a handle for the specified child device.
1334 This function checks to see if the driver specified by This supports the device specified by
1335 ControllerHandle. Drivers typically use the device path attached to
1336 ControllerHandle and/or the services from the bus I/O abstraction attached to
1337 ControllerHandle to determine if the driver supports ControllerHandle. This function
1338 may be called many times during platform initialization. In order to reduce boot times, the tests
1339 performed by this function must be very small and take as little time as possible to execute. This
1340 function must not change the state of any hardware devices, and this function must be aware that the
1341 device specified by ControllerHandle may already be managed by the same driver or a
1342 different driver. This function must match its calls to AllocatePages() with FreePages(),
1343 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1344 Since ControllerHandle may have been previously started by the same driver, if a protocol is
1345 already in the opened state, then it must not be closed with CloseProtocol(). This is required
1346 to guarantee the state of ControllerHandle is not modified by this function.
1348 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1349 @param[in] ControllerHandle The handle of the controller to test. This handle
1350 must support a protocol interface that supplies
1351 an I/O abstraction to the driver.
1352 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1353 parameter is ignored by device drivers, and is optional for bus
1354 drivers. For bus drivers, if this parameter is not NULL, then
1355 the bus driver must determine if the bus controller specified
1356 by ControllerHandle and the child controller specified
1357 by RemainingDevicePath are both supported by this
1360 @retval EFI_SUCCESS The device specified by ControllerHandle and
1361 RemainingDevicePath is supported by the driver specified by This.
1362 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
1363 RemainingDevicePath is already managed by the driver
1365 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
1366 RemainingDevicePath is already managed by a different
1367 driver or an application that requires exclusive access.
1368 Currently not implemented.
1369 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
1370 RemainingDevicePath is not supported by the driver specified by This.
1374 IScsiIp6DriverBindingSupported (
1375 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1376 IN EFI_HANDLE ControllerHandle
,
1377 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1380 return IScsiSupported (
1383 RemainingDevicePath
,
1389 Starts a device controller or a bus controller.
1391 The Start() function is designed to be invoked from the EFI boot service ConnectController().
1392 As a result, much of the error checking on the parameters to Start() has been moved into this
1393 common boot service. It is legal to call Start() from other locations,
1394 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1395 1. ControllerHandle must be a valid EFI_HANDLE.
1396 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1397 EFI_DEVICE_PATH_PROTOCOL.
1398 3. Prior to calling Start(), the Supported() function for the driver specified by This must
1399 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1401 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1402 @param[in] ControllerHandle The handle of the controller to start. This handle
1403 must support a protocol interface that supplies
1404 an I/O abstraction to the driver.
1405 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
1406 parameter is ignored by device drivers, and is optional for bus
1407 drivers. For a bus driver, if this parameter is NULL, then handles
1408 for all the children of Controller are created by this driver.
1409 If this parameter is not NULL and the first Device Path Node is
1410 not the End of Device Path Node, then only the handle for the
1411 child device specified by the first Device Path Node of
1412 RemainingDevicePath is created by this driver.
1413 If the first Device Path Node of RemainingDevicePath is
1414 the End of Device Path Node, no child handle is created by this
1417 @retval EFI_SUCCESS The device was started.
1418 @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
1419 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1420 @retval Others The driver failed to start the device.
1425 IScsiIp6DriverBindingStart (
1426 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1427 IN EFI_HANDLE ControllerHandle
,
1428 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1433 Status
= IScsiStart (This
->DriverBindingHandle
, ControllerHandle
, IP_VERSION_6
);
1434 if (Status
== EFI_ALREADY_STARTED
) {
1435 Status
= EFI_SUCCESS
;
1442 Stops a device controller or a bus controller.
1444 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1445 As a result, much of the error checking on the parameters to Stop() has been moved
1446 into this common boot service. It is legal to call Stop() from other locations,
1447 but the following calling restrictions must be followed or the system behavior will not be deterministic.
1448 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1449 same driver's Start() function.
1450 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1451 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1452 Start() function, and the Start() function must have called OpenProtocol() on
1453 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1455 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1456 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1457 support a bus specific I/O protocol for the driver
1458 to use to stop the device.
1459 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1460 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1461 if NumberOfChildren is 0.
1463 @retval EFI_SUCCESS The device was stopped.
1464 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1469 IScsiIp6DriverBindingStop (
1470 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1471 IN EFI_HANDLE ControllerHandle
,
1472 IN UINTN NumberOfChildren
,
1473 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1486 Unload the iSCSI driver.
1488 @param[in] ImageHandle The handle of the driver image.
1490 @retval EFI_SUCCESS The driver is unloaded.
1491 @retval EFI_DEVICE_ERROR An unexpected error occurred.
1497 IN EFI_HANDLE ImageHandle
1501 UINTN DeviceHandleCount
;
1502 EFI_HANDLE
*DeviceHandleBuffer
;
1504 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
1505 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
1508 // Try to disonnect the driver from the devices it's controlling.
1510 Status
= gBS
->LocateHandleBuffer (
1517 if (EFI_ERROR (Status
)) {
1522 // Disconnect the iSCSI4 driver from the controlled device.
1524 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1525 Status
= IScsiTestManagedDevice (
1526 DeviceHandleBuffer
[Index
],
1527 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1528 &gEfiTcp4ProtocolGuid
)
1530 if (EFI_ERROR (Status
)) {
1533 Status
= gBS
->DisconnectController (
1534 DeviceHandleBuffer
[Index
],
1535 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1538 if (EFI_ERROR (Status
)) {
1544 // Disconnect the iSCSI6 driver from the controlled device.
1546 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
1547 Status
= IScsiTestManagedDevice (
1548 DeviceHandleBuffer
[Index
],
1549 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1550 &gEfiTcp6ProtocolGuid
1552 if (EFI_ERROR (Status
)) {
1555 Status
= gBS
->DisconnectController (
1556 DeviceHandleBuffer
[Index
],
1557 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1560 if (EFI_ERROR (Status
)) {
1566 // Unload the iSCSI configuration form.
1568 Status
= IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1569 if (EFI_ERROR (Status
)) {
1574 // Uninstall the protocols installed by iSCSI driver.
1576 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1578 &gEfiAuthenticationInfoProtocolGuid
,
1579 &gIScsiAuthenticationInfo
,
1582 if (EFI_ERROR (Status
)) {
1586 if (gIScsiControllerNameTable
!= NULL
) {
1587 Status
= FreeUnicodeStringTable (gIScsiControllerNameTable
);
1588 if (EFI_ERROR (Status
)) {
1591 gIScsiControllerNameTable
= NULL
;
1595 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
1596 // if it has been installed.
1598 Status
= gBS
->HandleProtocol (
1599 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1600 &gEfiComponentNameProtocolGuid
,
1601 (VOID
**) &ComponentName
1603 if (!EFI_ERROR (Status
)) {
1604 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1605 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1606 &gEfiComponentNameProtocolGuid
,
1610 if (EFI_ERROR (Status
)) {
1615 Status
= gBS
->HandleProtocol (
1616 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1617 &gEfiComponentName2ProtocolGuid
,
1618 (VOID
**) &ComponentName2
1620 if (!EFI_ERROR (Status
)) {
1621 gBS
->UninstallMultipleProtocolInterfaces (
1622 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1623 &gEfiComponentName2ProtocolGuid
,
1627 if (EFI_ERROR (Status
)) {
1633 // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
1634 // if it has been installed.
1636 Status
= gBS
->HandleProtocol (
1637 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1638 &gEfiComponentNameProtocolGuid
,
1639 (VOID
**) &ComponentName
1641 if (!EFI_ERROR (Status
)) {
1642 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1643 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1644 &gEfiComponentNameProtocolGuid
,
1648 if (EFI_ERROR (Status
)) {
1653 Status
= gBS
->HandleProtocol (
1654 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1655 &gEfiComponentName2ProtocolGuid
,
1656 (VOID
**) &ComponentName2
1658 if (!EFI_ERROR (Status
)) {
1659 gBS
->UninstallMultipleProtocolInterfaces (
1660 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1661 &gEfiComponentName2ProtocolGuid
,
1665 if (EFI_ERROR (Status
)) {
1671 // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
1673 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1674 gIScsiIp4DriverBinding
.DriverBindingHandle
,
1675 &gEfiDriverBindingProtocolGuid
,
1676 &gIScsiIp4DriverBinding
,
1677 &gEfiIScsiInitiatorNameProtocolGuid
,
1678 &gIScsiInitiatorName
,
1681 if (EFI_ERROR (Status
)) {
1685 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1686 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1687 &gEfiDriverBindingProtocolGuid
,
1688 &gIScsiIp6DriverBinding
,
1694 if (DeviceHandleBuffer
!= NULL
) {
1695 FreePool (DeviceHandleBuffer
);
1702 This is the declaration of an EFI image entry point. This entry point is
1703 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1704 both device drivers and bus drivers.
1706 The entry point for iSCSI driver which initializes the global variables and
1707 installs the driver binding, component name protocol, iSCSI initiator name
1708 protocol and Authentication Info protocol on its image.
1710 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1711 @param[in] SystemTable A pointer to the EFI System Table.
1713 @retval EFI_SUCCESS The operation completed successfully.
1714 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1719 IScsiDriverEntryPoint (
1720 IN EFI_HANDLE ImageHandle
,
1721 IN EFI_SYSTEM_TABLE
*SystemTable
1725 EFI_ISCSI_INITIATOR_NAME_PROTOCOL
*IScsiInitiatorName
;
1726 EFI_AUTHENTICATION_INFO_PROTOCOL
*AuthenticationInfo
;
1729 // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
1731 Status
= gBS
->LocateProtocol (
1732 &gEfiIScsiInitiatorNameProtocolGuid
,
1734 (VOID
**) &IScsiInitiatorName
1736 if (!EFI_ERROR (Status
)) {
1737 return EFI_ACCESS_DENIED
;
1741 // Initialize the EFI Driver Library.
1743 Status
= EfiLibInstallDriverBindingComponentName2 (
1746 &gIScsiIp4DriverBinding
,
1748 &gIScsiComponentName
,
1749 &gIScsiComponentName2
1751 if (EFI_ERROR (Status
)) {
1755 Status
= EfiLibInstallDriverBindingComponentName2 (
1758 &gIScsiIp6DriverBinding
,
1760 &gIScsiComponentName
,
1761 &gIScsiComponentName2
1763 if (EFI_ERROR (Status
)) {
1768 // Install the iSCSI Initiator Name Protocol.
1770 Status
= gBS
->InstallProtocolInterface (
1772 &gEfiIScsiInitiatorNameProtocolGuid
,
1773 EFI_NATIVE_INTERFACE
,
1774 &gIScsiInitiatorName
1776 if (EFI_ERROR (Status
)) {
1781 // Create the private data structures.
1783 mPrivate
= AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA
));
1784 if (mPrivate
== NULL
) {
1785 Status
= EFI_OUT_OF_RESOURCES
;
1789 InitializeListHead (&mPrivate
->NicInfoList
);
1790 InitializeListHead (&mPrivate
->AttemptConfigs
);
1793 // Initialize the configuration form of iSCSI.
1795 Status
= IScsiConfigFormInit (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1796 if (EFI_ERROR (Status
)) {
1801 // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
1802 // do not produce the protocol instance.
1804 Status
= gBS
->LocateProtocol (
1805 &gEfiAuthenticationInfoProtocolGuid
,
1807 (VOID
**) &AuthenticationInfo
1809 if (Status
== EFI_NOT_FOUND
) {
1810 Status
= gBS
->InstallProtocolInterface (
1812 &gEfiAuthenticationInfoProtocolGuid
,
1813 EFI_NATIVE_INTERFACE
,
1814 &gIScsiAuthenticationInfo
1816 if (EFI_ERROR (Status
)) {
1824 IScsiConfigFormUnload (gIScsiIp4DriverBinding
.DriverBindingHandle
);
1827 FreePool (mPrivate
);
1830 gBS
->UninstallMultipleProtocolInterfaces (
1832 &gEfiIScsiInitiatorNameProtocolGuid
,
1833 &gIScsiInitiatorName
,
1838 gBS
->UninstallMultipleProtocolInterfaces (
1839 gIScsiIp6DriverBinding
.DriverBindingHandle
,
1840 &gEfiDriverBindingProtocolGuid
,
1841 &gIScsiIp6DriverBinding
,
1842 &gEfiComponentName2ProtocolGuid
,
1843 &gIScsiComponentName2
,
1844 &gEfiComponentNameProtocolGuid
,
1845 &gIScsiComponentName
,
1850 gBS
->UninstallMultipleProtocolInterfaces (
1852 &gEfiDriverBindingProtocolGuid
,
1853 &gIScsiIp4DriverBinding
,
1854 &gEfiComponentName2ProtocolGuid
,
1855 &gIScsiComponentName2
,
1856 &gEfiComponentNameProtocolGuid
,
1857 &gIScsiComponentName
,