1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891 |
- /** @file
- The entry point of IScsi driver.
- Copyright (c) 2019, NVIDIA Corporation. All rights reserved.
- Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
- (C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "IScsiImpl.h"
- EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding = {
- IScsiIp4DriverBindingSupported,
- IScsiIp4DriverBindingStart,
- IScsiIp4DriverBindingStop,
- 0xa,
- NULL,
- NULL
- };
- EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding = {
- IScsiIp6DriverBindingSupported,
- IScsiIp6DriverBindingStart,
- IScsiIp6DriverBindingStop,
- 0xa,
- NULL,
- NULL
- };
- EFI_GUID gIScsiV4PrivateGuid = ISCSI_V4_PRIVATE_GUID;
- EFI_GUID gIScsiV6PrivateGuid = ISCSI_V6_PRIVATE_GUID;
- ISCSI_PRIVATE_DATA *mPrivate = NULL;
- /**
- Tests to see if this driver supports the RemainingDevicePath.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For bus drivers, if this parameter is not NULL, then
- the bus driver must determine if the bus controller specified
- by ControllerHandle and the child controller specified
- by RemainingDevicePath are both supported by this
- bus driver.
- @retval EFI_SUCCESS The RemainingDevicePath is supported or NULL.
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
- RemainingDevicePath is not supported by the driver specified by This.
- **/
- EFI_STATUS
- IScsiIsDevicePathSupported (
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
- {
- EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
- CurrentDevicePath = RemainingDevicePath;
- if (CurrentDevicePath != NULL) {
- while (!IsDevicePathEnd (CurrentDevicePath)) {
- if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {
- return EFI_SUCCESS;
- }
- CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);
- }
- return EFI_UNSUPPORTED;
- }
- return EFI_SUCCESS;
- }
- /**
- Check whether an iSCSI HBA adapter already installs an AIP instance with
- network boot policy matching the value specified in PcdIScsiAIPNetworkBootPolicy.
- If yes, return EFI_SUCCESS.
- @retval EFI_SUCCESS Found an AIP with matching network boot policy.
- @retval EFI_NOT_FOUND AIP is unavailable or the network boot policy
- not matched.
- **/
- EFI_STATUS
- IScsiCheckAip (
- VOID
- )
- {
- UINTN AipHandleCount;
- EFI_HANDLE *AipHandleBuffer;
- UINTN AipIndex;
- EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;
- EFI_GUID *InfoTypesBuffer;
- UINTN InfoTypeBufferCount;
- UINTN TypeIndex;
- VOID *InfoBlock;
- UINTN InfoBlockSize;
- BOOLEAN Supported;
- EFI_ADAPTER_INFO_NETWORK_BOOT *NetworkBoot;
- EFI_STATUS Status;
- UINT8 NetworkBootPolicy;
- //
- // Check any AIP instances exist in system.
- //
- AipHandleCount = 0;
- AipHandleBuffer = NULL;
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiAdapterInformationProtocolGuid,
- NULL,
- &AipHandleCount,
- &AipHandleBuffer
- );
- if (EFI_ERROR (Status) || (AipHandleCount == 0)) {
- return EFI_NOT_FOUND;
- }
- ASSERT (AipHandleBuffer != NULL);
- InfoBlock = NULL;
- for (AipIndex = 0; AipIndex < AipHandleCount; AipIndex++) {
- Status = gBS->HandleProtocol (
- AipHandleBuffer[AipIndex],
- &gEfiAdapterInformationProtocolGuid,
- (VOID *)&Aip
- );
- ASSERT_EFI_ERROR (Status);
- ASSERT (Aip != NULL);
- Status = gBS->HandleProtocol (
- AipHandleBuffer[AipIndex],
- &gEfiExtScsiPassThruProtocolGuid,
- (VOID *)&ExtScsiPassThru
- );
- if (EFI_ERROR (Status) || (ExtScsiPassThru == NULL)) {
- continue;
- }
- InfoTypesBuffer = NULL;
- InfoTypeBufferCount = 0;
- Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
- if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL)) {
- continue;
- }
- //
- // Check whether the AIP instance has Network boot information block.
- //
- Supported = FALSE;
- for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
- if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoNetworkBootGuid)) {
- Supported = TRUE;
- break;
- }
- }
- FreePool (InfoTypesBuffer);
- if (!Supported) {
- continue;
- }
- //
- // We now have network boot information block.
- //
- InfoBlock = NULL;
- InfoBlockSize = 0;
- Status = Aip->GetInformation (Aip, &gEfiAdapterInfoNetworkBootGuid, &InfoBlock, &InfoBlockSize);
- if (EFI_ERROR (Status) || (InfoBlock == NULL)) {
- continue;
- }
- //
- // Check whether the network boot policy matches.
- //
- NetworkBoot = (EFI_ADAPTER_INFO_NETWORK_BOOT *)InfoBlock;
- NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);
- if (NetworkBootPolicy == STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP) {
- Status = EFI_SUCCESS;
- goto Exit;
- }
- if ((((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP4) != 0) &&
- !NetworkBoot->iScsiIpv4BootCapablity) ||
- (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_IP6) != 0) &&
- !NetworkBoot->iScsiIpv6BootCapablity) ||
- (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_OFFLOAD) != 0) &&
- !NetworkBoot->OffloadCapability) ||
- (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_SUPPORT_MPIO) != 0) &&
- !NetworkBoot->iScsiMpioCapability) ||
- (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP4) != 0) &&
- !NetworkBoot->iScsiIpv4Boot) ||
- (((NetworkBootPolicy & STOP_UEFI_ISCSI_IF_AIP_CONFIGURED_IP6) != 0) &&
- !NetworkBoot->iScsiIpv6Boot))
- {
- FreePool (InfoBlock);
- continue;
- }
- Status = EFI_SUCCESS;
- goto Exit;
- }
- Status = EFI_NOT_FOUND;
- Exit:
- if (InfoBlock != NULL) {
- FreePool (InfoBlock);
- }
- if (AipHandleBuffer != NULL) {
- FreePool (AipHandleBuffer);
- }
- return Status;
- }
- /**
- Tests to see if this driver supports a given controller. This is the worker function for
- IScsiIp4(6)DriverBindingSupported.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to test. This handle
- must support a protocol interface that supplies
- an I/O abstraction to the driver.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For bus drivers, if this parameter is not NULL, then
- the bus driver must determine if the bus controller specified
- by ControllerHandle and the child controller specified
- by RemainingDevicePath are both supported by this
- bus driver.
- @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
- @retval EFI_SUCCESS The device specified by ControllerHandle and
- RemainingDevicePath is supported by the driver specified by This.
- @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
- RemainingDevicePath is already being managed by the driver
- specified by This.
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
- RemainingDevicePath is not supported by the driver specified by This.
- **/
- EFI_STATUS
- EFIAPI
- IScsiSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
- IN UINT8 IpVersion
- )
- {
- EFI_STATUS Status;
- EFI_GUID *IScsiServiceBindingGuid;
- EFI_GUID *TcpServiceBindingGuid;
- EFI_GUID *DhcpServiceBindingGuid;
- EFI_GUID *DnsServiceBindingGuid;
- if (IpVersion == IP_VERSION_4) {
- IScsiServiceBindingGuid = &gIScsiV4PrivateGuid;
- TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
- DhcpServiceBindingGuid = &gEfiDhcp4ServiceBindingProtocolGuid;
- DnsServiceBindingGuid = &gEfiDns4ServiceBindingProtocolGuid;
- } else {
- IScsiServiceBindingGuid = &gIScsiV6PrivateGuid;
- TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
- DhcpServiceBindingGuid = &gEfiDhcp6ServiceBindingProtocolGuid;
- DnsServiceBindingGuid = &gEfiDns6ServiceBindingProtocolGuid;
- }
- Status = gBS->OpenProtocol (
- ControllerHandle,
- IScsiServiceBindingGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- return EFI_ALREADY_STARTED;
- }
- Status = gBS->OpenProtocol (
- ControllerHandle,
- TcpServiceBindingGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- Status = IScsiIsDevicePathSupported (RemainingDevicePath);
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- if (IScsiDhcpIsConfigured (ControllerHandle, IpVersion)) {
- Status = gBS->OpenProtocol (
- ControllerHandle,
- DhcpServiceBindingGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- }
- if (IScsiDnsIsConfigured (ControllerHandle)) {
- Status = gBS->OpenProtocol (
- ControllerHandle,
- DnsServiceBindingGuid,
- NULL,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Start to manage the controller. This is the worker function for
- IScsiIp4(6)DriverBindingStart.
- @param[in] Image Handle of the image.
- @param[in] ControllerHandle Handle of the controller.
- @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
- @retval EFI_SUCCESS This driver was started.
- @retval EFI_ALREADY_STARTED This driver is already running on this device.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
- @retval EFI_NOT_FOUND There is no sufficient information to establish
- the iScsi session.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval EFI_DEVICE_ERROR Failed to get TCP connection device path.
- @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
- because its interfaces are being used.
- **/
- EFI_STATUS
- IScsiStart (
- IN EFI_HANDLE Image,
- IN EFI_HANDLE ControllerHandle,
- IN UINT8 IpVersion
- )
- {
- EFI_STATUS Status;
- ISCSI_DRIVER_DATA *Private;
- LIST_ENTRY *Entry;
- LIST_ENTRY *NextEntry;
- ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
- ISCSI_SESSION *Session;
- UINT8 Index;
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExistIScsiExtScsiPassThru;
- ISCSI_DRIVER_DATA *ExistPrivate;
- UINT8 *AttemptConfigOrder;
- UINTN AttemptConfigOrderSize;
- UINT8 BootSelected;
- EFI_HANDLE *HandleBuffer;
- UINTN NumberOfHandles;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_GUID *IScsiPrivateGuid;
- EFI_GUID *TcpServiceBindingGuid;
- BOOLEAN NeedUpdate;
- VOID *Interface;
- EFI_GUID *ProtocolGuid;
- UINT8 NetworkBootPolicy;
- ISCSI_SESSION_CONFIG_NVDATA *NvData;
- //
- // Test to see if iSCSI driver supports the given controller.
- //
- if (IpVersion == IP_VERSION_4) {
- IScsiPrivateGuid = &gIScsiV4PrivateGuid;
- TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
- ProtocolGuid = &gEfiTcp4ProtocolGuid;
- } else if (IpVersion == IP_VERSION_6) {
- IScsiPrivateGuid = &gIScsiV6PrivateGuid;
- TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
- ProtocolGuid = &gEfiTcp6ProtocolGuid;
- } else {
- return EFI_INVALID_PARAMETER;
- }
- Status = gBS->OpenProtocol (
- ControllerHandle,
- IScsiPrivateGuid,
- NULL,
- Image,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- return EFI_ALREADY_STARTED;
- }
- Status = gBS->OpenProtocol (
- ControllerHandle,
- TcpServiceBindingGuid,
- NULL,
- Image,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);
- if (NetworkBootPolicy == ALWAYS_USE_ISCSI_HBA_AND_IGNORE_UEFI_ISCSI) {
- return EFI_ABORTED;
- }
- if (NetworkBootPolicy != ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_ISCSI_HBA) {
- //
- // Check existing iSCSI AIP.
- //
- Status = IScsiCheckAip ();
- if (!EFI_ERROR (Status)) {
- //
- // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
- //
- return EFI_ABORTED;
- }
- }
- //
- // Record the incoming NIC info.
- //
- Status = IScsiAddNic (ControllerHandle, Image);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Create the instance private data.
- //
- Private = IScsiCreateDriverData (Image, ControllerHandle);
- if (Private == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
- // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
- // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
- // IScsiDriverBindingStop() will be called.
- //
- Status = NetLibCreateServiceChild (
- ControllerHandle,
- Image,
- TcpServiceBindingGuid,
- &Private->ChildHandle
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- Status = gBS->OpenProtocol (
- Private->ChildHandle, /// Default Tcp child
- ProtocolGuid,
- &Interface,
- Image,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Always install private protocol no matter what happens later. We need to
- // keep the relationship between ControllerHandle and ChildHandle.
- //
- Status = gBS->InstallProtocolInterface (
- &ControllerHandle,
- IScsiPrivateGuid,
- EFI_NATIVE_INTERFACE,
- &Private->IScsiIdentifier
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- if (IpVersion == IP_VERSION_4) {
- mPrivate->Ipv6Flag = FALSE;
- } else {
- mPrivate->Ipv6Flag = TRUE;
- }
- //
- // Get the current iSCSI configuration data.
- //
- Status = IScsiGetConfigData (Private);
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // If there is already a successul attempt, check whether this attempt is the
- // first "enabled for MPIO" attempt. If not, still try the first attempt.
- // In single path mode, try all attempts.
- //
- ExistPrivate = NULL;
- Status = EFI_NOT_FOUND;
- if (mPrivate->OneSessionEstablished && mPrivate->EnableMpio) {
- AttemptConfigData = NULL;
- NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
- AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
- if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
- break;
- }
- }
- if (AttemptConfigData == NULL) {
- goto ON_ERROR;
- }
- if (AttemptConfigData->AttemptConfigIndex == mPrivate->BootSelectedIndex) {
- goto ON_EXIT;
- }
- //
- // Uninstall the original ExtScsiPassThru first.
- //
- //
- // Locate all ExtScsiPassThru protocol instances.
- //
- Status = gBS->LocateHandleBuffer (
- ByProtocol,
- &gEfiExtScsiPassThruProtocolGuid,
- NULL,
- &NumberOfHandles,
- &HandleBuffer
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // Find ExtScsiPassThru protocol instance produced by this driver.
- //
- ExistIScsiExtScsiPassThru = NULL;
- for (Index = 0; Index < NumberOfHandles && ExistIScsiExtScsiPassThru == NULL; Index++) {
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiDevicePathProtocolGuid,
- (VOID **)&DevicePath
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
- while (!IsDevicePathEnd (DevicePath)) {
- if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_MAC_ADDR_DP)) {
- //
- // Get the ExtScsiPassThru protocol instance.
- //
- Status = gBS->HandleProtocol (
- HandleBuffer[Index],
- &gEfiExtScsiPassThruProtocolGuid,
- (VOID **)&ExistIScsiExtScsiPassThru
- );
- ASSERT_EFI_ERROR (Status);
- break;
- }
- DevicePath = NextDevicePathNode (DevicePath);
- }
- }
- FreePool (HandleBuffer);
- if (ExistIScsiExtScsiPassThru == NULL) {
- Status = EFI_NOT_FOUND;
- goto ON_ERROR;
- }
- ExistPrivate = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru);
- Status = gBS->UninstallProtocolInterface (
- ExistPrivate->ExtScsiPassThruHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- &ExistPrivate->IScsiExtScsiPassThru
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- }
- //
- // Install the Ext SCSI PASS THRU protocol.
- //
- Status = gBS->InstallProtocolInterface (
- &Private->ExtScsiPassThruHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &Private->IScsiExtScsiPassThru
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- BootSelected = 0;
- NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
- AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
- //
- // Don't process the attempt that does not associate with the current NIC or
- // this attempt is disabled or established.
- //
- if ((AttemptConfigData->NicIndex != mPrivate->CurrentNic) ||
- (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) ||
- AttemptConfigData->ValidPath)
- {
- continue;
- }
- //
- // In multipath mode, don't process attempts configured for single path.
- // In default single path mode, don't process attempts configured for multipath.
- //
- if ((mPrivate->EnableMpio &&
- (AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO)) ||
- (!mPrivate->EnableMpio &&
- (AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED)))
- {
- continue;
- }
- //
- // Don't process the attempt that fails to get the init/target information from DHCP.
- //
- if (AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp &&
- !AttemptConfigData->DhcpSuccess)
- {
- if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {
- mPrivate->ValidSinglePathCount--;
- }
- continue;
- }
- //
- // Don't process the autoconfigure path if it is already established.
- //
- if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&
- AttemptConfigData->AutoConfigureSuccess)
- {
- continue;
- }
- //
- // Don't process the attempt if its IP mode is not in the current IP version.
- //
- if (!mPrivate->Ipv6Flag) {
- if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
- continue;
- }
- if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&
- (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6))
- {
- continue;
- }
- } else {
- if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
- continue;
- }
- if ((AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) &&
- (AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4))
- {
- continue;
- }
- }
- //
- // Fill in the Session and init it.
- //
- Session = (ISCSI_SESSION *)AllocateZeroPool (sizeof (ISCSI_SESSION));
- if (Session == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto ON_ERROR;
- }
- Session->Private = Private;
- Session->ConfigData = AttemptConfigData;
- Session->AuthType = AttemptConfigData->AuthenticationType;
- UnicodeSPrint (
- mPrivate->PortString,
- (UINTN)ISCSI_NAME_IFR_MAX_SIZE,
- L"Attempt %d",
- (UINTN)AttemptConfigData->AttemptConfigIndex
- );
- if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) {
- Session->AuthData.CHAP.AuthConfig = &AttemptConfigData->AuthConfigData.CHAP;
- }
- IScsiSessionInit (Session, FALSE);
- //
- // Try to login and create an iSCSI session according to the configuration.
- //
- Status = IScsiSessionLogin (Session);
- if (Status == EFI_MEDIA_CHANGED) {
- //
- // The specified target is not available, and the redirection information is
- // received. Login the session again with the updated target address.
- //
- Status = IScsiSessionLogin (Session);
- } else if (Status == EFI_NOT_READY) {
- Status = IScsiSessionReLogin (Session);
- }
- //
- // Restore the original user setting which specifies the proxy/virtual iSCSI target to NV region.
- //
- NvData = &AttemptConfigData->SessionConfigData;
- if (NvData->RedirectFlag) {
- NvData->TargetPort = NvData->OriginalTargetPort;
- CopyMem (&NvData->TargetIp, &NvData->OriginalTargetIp, sizeof (EFI_IP_ADDRESS));
- NvData->RedirectFlag = FALSE;
- gRT->SetVariable (
- mPrivate->PortString,
- &gEfiIScsiInitiatorNameProtocolGuid,
- ISCSI_CONFIG_VAR_ATTR,
- sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
- AttemptConfigData
- );
- }
- if (EFI_ERROR (Status)) {
- //
- // In Single path mode, only the successful attempt will be recorded in iBFT;
- // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
- //
- if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {
- mPrivate->ValidSinglePathCount--;
- }
- FreePool (Session);
- } else {
- AttemptConfigData->ValidPath = TRUE;
- //
- // Do not record the attempt in iBFT if it login with KRB5.
- // TODO: record KRB5 attempt information in the iSCSI device path.
- //
- if (Session->AuthType == ISCSI_AUTH_TYPE_KRB) {
- if (!mPrivate->EnableMpio && (mPrivate->ValidSinglePathCount > 0)) {
- mPrivate->ValidSinglePathCount--;
- }
- AttemptConfigData->ValidiBFTPath = FALSE;
- } else {
- AttemptConfigData->ValidiBFTPath = TRUE;
- }
- //
- // IScsi session success. Update the attempt state to NVR.
- //
- if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
- AttemptConfigData->AutoConfigureSuccess = TRUE;
- }
- gRT->SetVariable (
- mPrivate->PortString,
- &gEfiIScsiInitiatorNameProtocolGuid,
- ISCSI_CONFIG_VAR_ATTR,
- sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
- AttemptConfigData
- );
- //
- // Select the first login session. Abort others.
- //
- if (Private->Session == NULL) {
- Private->Session = Session;
- BootSelected = AttemptConfigData->AttemptConfigIndex;
- //
- // Don't validate other attempt in multipath mode if one is success.
- //
- if (mPrivate->EnableMpio) {
- break;
- }
- } else {
- IScsiSessionAbort (Session);
- FreePool (Session);
- }
- }
- }
- //
- // All attempts configured for this driver instance are not valid.
- //
- if (Private->Session == NULL) {
- Status = gBS->UninstallProtocolInterface (
- Private->ExtScsiPassThruHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- &Private->IScsiExtScsiPassThru
- );
- ASSERT_EFI_ERROR (Status);
- Private->ExtScsiPassThruHandle = NULL;
- //
- // Reinstall the original ExtScsiPassThru back.
- //
- if (mPrivate->OneSessionEstablished && (ExistPrivate != NULL)) {
- Status = gBS->InstallProtocolInterface (
- &ExistPrivate->ExtScsiPassThruHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &ExistPrivate->IScsiExtScsiPassThru
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- goto ON_EXIT;
- }
- Status = EFI_NOT_FOUND;
- goto ON_ERROR;
- }
- NeedUpdate = TRUE;
- //
- // More than one attempt successes.
- //
- if ((Private->Session != NULL) && mPrivate->OneSessionEstablished) {
- AttemptConfigOrder = IScsiGetVariableAndSize (
- L"AttemptOrder",
- &gIScsiConfigGuid,
- &AttemptConfigOrderSize
- );
- if (AttemptConfigOrder == NULL) {
- goto ON_ERROR;
- }
- for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
- if ((AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) ||
- (AttemptConfigOrder[Index] == BootSelected))
- {
- break;
- }
- }
- if (mPrivate->EnableMpio) {
- //
- // Use the attempt in earlier order. Abort the later one in MPIO.
- //
- if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {
- IScsiSessionAbort (Private->Session);
- FreePool (Private->Session);
- Private->Session = NULL;
- gBS->UninstallProtocolInterface (
- Private->ExtScsiPassThruHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- &Private->IScsiExtScsiPassThru
- );
- Private->ExtScsiPassThruHandle = NULL;
- //
- // Reinstall the original ExtScsiPassThru back.
- //
- Status = gBS->InstallProtocolInterface (
- &ExistPrivate->ExtScsiPassThruHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &ExistPrivate->IScsiExtScsiPassThru
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- goto ON_EXIT;
- } else {
- if (AttemptConfigOrder[Index] != BootSelected) {
- goto ON_ERROR;
- }
- mPrivate->BootSelectedIndex = BootSelected;
- //
- // Clear the resource in ExistPrivate.
- //
- gBS->UninstallProtocolInterface (
- ExistPrivate->Controller,
- IScsiPrivateGuid,
- &ExistPrivate->IScsiIdentifier
- );
- IScsiRemoveNic (ExistPrivate->Controller);
- if (ExistPrivate->Session != NULL) {
- IScsiSessionAbort (ExistPrivate->Session);
- }
- if (ExistPrivate->DevicePath != NULL) {
- Status = gBS->UninstallProtocolInterface (
- ExistPrivate->ExtScsiPassThruHandle,
- &gEfiDevicePathProtocolGuid,
- ExistPrivate->DevicePath
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- FreePool (ExistPrivate->DevicePath);
- }
- gBS->CloseEvent (ExistPrivate->ExitBootServiceEvent);
- FreePool (ExistPrivate);
- }
- } else {
- //
- // Use the attempt in earlier order as boot selected in single path mode.
- //
- if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {
- NeedUpdate = FALSE;
- }
- }
- }
- if (NeedUpdate) {
- mPrivate->OneSessionEstablished = TRUE;
- mPrivate->BootSelectedIndex = BootSelected;
- }
- //
- // Duplicate the Session's tcp connection device path. The source port field
- // will be set to zero as one iSCSI session is comprised of several iSCSI
- // connections.
- //
- Private->DevicePath = IScsiGetTcpConnDevicePath (Private->Session);
- if (Private->DevicePath == NULL) {
- Status = EFI_DEVICE_ERROR;
- goto ON_ERROR;
- }
- //
- // Install the updated device path onto the ExtScsiPassThruHandle.
- //
- Status = gBS->InstallProtocolInterface (
- &Private->ExtScsiPassThruHandle,
- &gEfiDevicePathProtocolGuid,
- EFI_NATIVE_INTERFACE,
- Private->DevicePath
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- //
- // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
- //
- Status = gBS->OpenProtocol (
- Private->ChildHandle, /// Default Tcp child
- ProtocolGuid,
- &Interface,
- Image,
- Private->ExtScsiPassThruHandle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- if (EFI_ERROR (Status)) {
- gBS->UninstallMultipleProtocolInterfaces (
- Private->ExtScsiPassThruHandle,
- &gEfiExtScsiPassThruProtocolGuid,
- &Private->IScsiExtScsiPassThru,
- &gEfiDevicePathProtocolGuid,
- Private->DevicePath,
- NULL
- );
- goto ON_ERROR;
- }
- ON_EXIT:
- //
- // Update/Publish the iSCSI Boot Firmware Table.
- //
- if (mPrivate->BootSelectedIndex != 0) {
- IScsiPublishIbft ();
- }
- return EFI_SUCCESS;
- ON_ERROR:
- if (Private->Session != NULL) {
- IScsiSessionAbort (Private->Session);
- }
- return Status;
- }
- /**
- Stops a device controller or a bus controller. This is the worker function for
- IScsiIp4(6)DriverBindingStop.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle A handle to the device being stopped. The handle must
- support a bus specific I/O protocol for the driver
- to use to stop the device.
- @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
- @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
- if NumberOfChildren is 0.
- @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
- @retval EFI_SUCCESS The device was stopped.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
- @retval EFI_INVALID_PARAMETER Child handle is NULL.
- @retval EFI_ACCESS_DENIED The protocol could not be removed from the Handle
- because its interfaces are being used.
- **/
- EFI_STATUS
- EFIAPI
- IScsiStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer OPTIONAL,
- IN UINT8 IpVersion
- )
- {
- EFI_HANDLE IScsiController;
- EFI_STATUS Status;
- ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
- ISCSI_DRIVER_DATA *Private;
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
- ISCSI_CONNECTION *Conn;
- EFI_GUID *ProtocolGuid;
- EFI_GUID *TcpServiceBindingGuid;
- EFI_GUID *TcpProtocolGuid;
- if (NumberOfChildren != 0) {
- //
- // We should have only one child.
- //
- Status = gBS->OpenProtocol (
- ChildHandleBuffer[0],
- &gEfiExtScsiPassThruProtocolGuid,
- (VOID **)&PassThru,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
- Conn = NET_LIST_HEAD (&Private->Session->Conns, ISCSI_CONNECTION, Link);
- //
- // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
- // the protocol here, but do not uninstall the device path protocol and
- // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
- //
- if (IpVersion == IP_VERSION_4) {
- ProtocolGuid = &gEfiTcp4ProtocolGuid;
- } else {
- ProtocolGuid = &gEfiTcp6ProtocolGuid;
- }
- gBS->CloseProtocol (
- Private->ChildHandle,
- ProtocolGuid,
- Private->Image,
- Private->ExtScsiPassThruHandle
- );
- gBS->CloseProtocol (
- Conn->TcpIo.Handle,
- ProtocolGuid,
- Private->Image,
- Private->ExtScsiPassThruHandle
- );
- return EFI_SUCCESS;
- }
- //
- // Get the handle of the controller we are controlling.
- //
- if (IpVersion == IP_VERSION_4) {
- ProtocolGuid = &gIScsiV4PrivateGuid;
- TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
- TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
- } else {
- ProtocolGuid = &gIScsiV6PrivateGuid;
- TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
- TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
- }
- IScsiController = NetLibGetNicHandle (ControllerHandle, TcpProtocolGuid);
- if (IScsiController == NULL) {
- return EFI_SUCCESS;
- }
- Status = gBS->OpenProtocol (
- IScsiController,
- ProtocolGuid,
- (VOID **)&IScsiIdentifier,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
- ASSERT (Private != NULL);
- if (Private->ChildHandle != NULL) {
- Status = gBS->CloseProtocol (
- Private->ChildHandle,
- TcpProtocolGuid,
- This->DriverBindingHandle,
- IScsiController
- );
- ASSERT (!EFI_ERROR (Status));
- Status = NetLibDestroyServiceChild (
- IScsiController,
- This->DriverBindingHandle,
- TcpServiceBindingGuid,
- Private->ChildHandle
- );
- ASSERT (!EFI_ERROR (Status));
- }
- gBS->UninstallProtocolInterface (
- IScsiController,
- ProtocolGuid,
- &Private->IScsiIdentifier
- );
- //
- // Remove this NIC.
- //
- IScsiRemoveNic (IScsiController);
- //
- // Update the iSCSI Boot Firmware Table.
- //
- IScsiPublishIbft ();
- if (Private->Session != NULL) {
- IScsiSessionAbort (Private->Session);
- }
- Status = IScsiCleanDriverData (Private);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- return EFI_SUCCESS;
- }
- /**
- Tests to see if this driver supports a given controller. If a child device is provided,
- it tests to see if this driver supports creating a handle for the specified child device.
- This function checks to see if the driver specified by This supports the device specified by
- ControllerHandle. Drivers typically use the device path attached to
- ControllerHandle and/or the services from the bus I/O abstraction attached to
- ControllerHandle to determine if the driver supports ControllerHandle. This function
- may be called many times during platform initialization. In order to reduce boot times, the tests
- performed by this function must be very small and take as little time as possible to execute. This
- function must not change the state of any hardware devices, and this function must be aware that the
- device specified by ControllerHandle may already be managed by the same driver or a
- different driver. This function must match its calls to AllocatePages() with FreePages(),
- AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
- Since ControllerHandle may have been previously started by the same driver, if a protocol is
- already in the opened state, then it must not be closed with CloseProtocol(). This is required
- to guarantee the state of ControllerHandle is not modified by this function.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to test. This handle
- must support a protocol interface that supplies
- an I/O abstraction to the driver.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For bus drivers, if this parameter is not NULL, then
- the bus driver must determine if the bus controller specified
- by ControllerHandle and the child controller specified
- by RemainingDevicePath are both supported by this
- bus driver.
- @retval EFI_SUCCESS The device specified by ControllerHandle and
- RemainingDevicePath is supported by the driver specified by This.
- @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
- RemainingDevicePath is already managed by the driver
- specified by This.
- @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
- RemainingDevicePath is already managed by a different
- driver or an application that requires exclusive access.
- Currently not implemented.
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
- RemainingDevicePath is not supported by the driver specified by This.
- **/
- EFI_STATUS
- EFIAPI
- IScsiIp4DriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
- {
- return IScsiSupported (
- This,
- ControllerHandle,
- RemainingDevicePath,
- IP_VERSION_4
- );
- }
- /**
- Starts a device controller or a bus controller.
- The Start() function is designed to be invoked from the EFI boot service ConnectController().
- As a result, much of the error checking on the parameters to Start() has been moved into this
- common boot service. It is legal to call Start() from other locations,
- but the following calling restrictions must be followed or the system behavior will not be deterministic.
- 1. ControllerHandle must be a valid EFI_HANDLE.
- 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
- EFI_DEVICE_PATH_PROTOCOL.
- 3. Prior to calling Start(), the Supported() function for the driver specified by This must
- have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to start. This handle
- must support a protocol interface that supplies
- an I/O abstraction to the driver.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For a bus driver, if this parameter is NULL, then handles
- for all the children of Controller are created by this driver.
- If this parameter is not NULL and the first Device Path Node is
- not the End of Device Path Node, then only the handle for the
- child device specified by the first Device Path Node of
- RemainingDevicePath is created by this driver.
- If the first Device Path Node of RemainingDevicePath is
- the End of Device Path Node, no child handle is created by this
- driver.
- @retval EFI_SUCCESS The device was started.
- @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval Others The driver failed to start the device.
- **/
- EFI_STATUS
- EFIAPI
- IScsiIp4DriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
- {
- EFI_STATUS Status;
- Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_4);
- if (Status == EFI_ALREADY_STARTED) {
- Status = EFI_SUCCESS;
- }
- return Status;
- }
- /**
- Stops a device controller or a bus controller.
- The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
- As a result, much of the error checking on the parameters to Stop() has been moved
- into this common boot service. It is legal to call Stop() from other locations,
- but the following calling restrictions must be followed or the system behavior will not be deterministic.
- 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
- same driver's Start() function.
- 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
- EFI_HANDLE. In addition, all of these handles must have been created in this driver's
- Start() function, and the Start() function must have called OpenProtocol() on
- ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle A handle to the device being stopped. The handle must
- support a bus specific I/O protocol for the driver
- to use to stop the device.
- @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
- @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
- if NumberOfChildren is 0.
- @retval EFI_SUCCESS The device was stopped.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
- **/
- EFI_STATUS
- EFIAPI
- IScsiIp4DriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
- )
- {
- return IScsiStop (
- This,
- ControllerHandle,
- NumberOfChildren,
- ChildHandleBuffer,
- IP_VERSION_4
- );
- }
- /**
- Tests to see if this driver supports a given controller. If a child device is provided,
- it tests to see if this driver supports creating a handle for the specified child device.
- This function checks to see if the driver specified by This supports the device specified by
- ControllerHandle. Drivers typically use the device path attached to
- ControllerHandle and/or the services from the bus I/O abstraction attached to
- ControllerHandle to determine if the driver supports ControllerHandle. This function
- may be called many times during platform initialization. In order to reduce boot times, the tests
- performed by this function must be very small and take as little time as possible to execute. This
- function must not change the state of any hardware devices, and this function must be aware that the
- device specified by ControllerHandle may already be managed by the same driver or a
- different driver. This function must match its calls to AllocatePages() with FreePages(),
- AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
- Since ControllerHandle may have been previously started by the same driver, if a protocol is
- already in the opened state, then it must not be closed with CloseProtocol(). This is required
- to guarantee the state of ControllerHandle is not modified by this function.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to test. This handle
- must support a protocol interface that supplies
- an I/O abstraction to the driver.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For bus drivers, if this parameter is not NULL, then
- the bus driver must determine if the bus controller specified
- by ControllerHandle and the child controller specified
- by RemainingDevicePath are both supported by this
- bus driver.
- @retval EFI_SUCCESS The device specified by ControllerHandle and
- RemainingDevicePath is supported by the driver specified by This.
- @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
- RemainingDevicePath is already managed by the driver
- specified by This.
- @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
- RemainingDevicePath is already managed by a different
- driver or an application that requires exclusive access.
- Currently not implemented.
- @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
- RemainingDevicePath is not supported by the driver specified by This.
- **/
- EFI_STATUS
- EFIAPI
- IScsiIp6DriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
- {
- return IScsiSupported (
- This,
- ControllerHandle,
- RemainingDevicePath,
- IP_VERSION_6
- );
- }
- /**
- Starts a device controller or a bus controller.
- The Start() function is designed to be invoked from the EFI boot service ConnectController().
- As a result, much of the error checking on the parameters to Start() has been moved into this
- common boot service. It is legal to call Start() from other locations,
- but the following calling restrictions must be followed or the system behavior will not be deterministic.
- 1. ControllerHandle must be a valid EFI_HANDLE.
- 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
- EFI_DEVICE_PATH_PROTOCOL.
- 3. Prior to calling Start(), the Supported() function for the driver specified by This must
- have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle The handle of the controller to start. This handle
- must support a protocol interface that supplies
- an I/O abstraction to the driver.
- @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
- parameter is ignored by device drivers, and is optional for bus
- drivers. For a bus driver, if this parameter is NULL, then handles
- for all the children of Controller are created by this driver.
- If this parameter is not NULL and the first Device Path Node is
- not the End of Device Path Node, then only the handle for the
- child device specified by the first Device Path Node of
- RemainingDevicePath is created by this driver.
- If the first Device Path Node of RemainingDevicePath is
- the End of Device Path Node, no child handle is created by this
- driver.
- @retval EFI_SUCCESS The device was started.
- @retval EFI_DEVICE_ERROR The device could not be started due to a device error. Currently not implemented.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- @retval Others The driver failed to start the device.
- **/
- EFI_STATUS
- EFIAPI
- IScsiIp6DriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
- )
- {
- EFI_STATUS Status;
- Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_6);
- if (Status == EFI_ALREADY_STARTED) {
- Status = EFI_SUCCESS;
- }
- return Status;
- }
- /**
- Stops a device controller or a bus controller.
- The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
- As a result, much of the error checking on the parameters to Stop() has been moved
- into this common boot service. It is legal to call Stop() from other locations,
- but the following calling restrictions must be followed or the system behavior will not be deterministic.
- 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
- same driver's Start() function.
- 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
- EFI_HANDLE. In addition, all of these handles must have been created in this driver's
- Start() function, and the Start() function must have called OpenProtocol() on
- ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
- @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
- @param[in] ControllerHandle A handle to the device being stopped. The handle must
- support a bus specific I/O protocol for the driver
- to use to stop the device.
- @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
- @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
- if NumberOfChildren is 0.
- @retval EFI_SUCCESS The device was stopped.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
- **/
- EFI_STATUS
- EFIAPI
- IScsiIp6DriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
- )
- {
- return IScsiStop (
- This,
- ControllerHandle,
- NumberOfChildren,
- ChildHandleBuffer,
- IP_VERSION_6
- );
- }
- /**
- Unload the iSCSI driver.
- @param[in] ImageHandle The handle of the driver image.
- @retval EFI_SUCCESS The driver is unloaded.
- @retval EFI_DEVICE_ERROR An unexpected error occurred.
- **/
- EFI_STATUS
- EFIAPI
- IScsiUnload (
- IN EFI_HANDLE ImageHandle
- )
- {
- EFI_STATUS Status;
- UINTN DeviceHandleCount;
- EFI_HANDLE *DeviceHandleBuffer;
- UINTN Index;
- EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
- EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
- //
- // Try to disconnect the driver from the devices it's controlling.
- //
- Status = gBS->LocateHandleBuffer (
- AllHandles,
- NULL,
- NULL,
- &DeviceHandleCount,
- &DeviceHandleBuffer
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Disconnect the iSCSI4 driver from the controlled device.
- //
- for (Index = 0; Index < DeviceHandleCount; Index++) {
- Status = IScsiTestManagedDevice (
- DeviceHandleBuffer[Index],
- gIScsiIp4DriverBinding.DriverBindingHandle,
- &gEfiTcp4ProtocolGuid
- )
- ;
- if (EFI_ERROR (Status)) {
- continue;
- }
- Status = gBS->DisconnectController (
- DeviceHandleBuffer[Index],
- gIScsiIp4DriverBinding.DriverBindingHandle,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- }
- //
- // Disconnect the iSCSI6 driver from the controlled device.
- //
- for (Index = 0; Index < DeviceHandleCount; Index++) {
- Status = IScsiTestManagedDevice (
- DeviceHandleBuffer[Index],
- gIScsiIp6DriverBinding.DriverBindingHandle,
- &gEfiTcp6ProtocolGuid
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
- Status = gBS->DisconnectController (
- DeviceHandleBuffer[Index],
- gIScsiIp6DriverBinding.DriverBindingHandle,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- }
- //
- // Unload the iSCSI configuration form.
- //
- Status = IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- //
- // Uninstall the protocols installed by iSCSI driver.
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ImageHandle,
- &gEfiAuthenticationInfoProtocolGuid,
- &gIScsiAuthenticationInfo,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- if (gIScsiControllerNameTable != NULL) {
- Status = FreeUnicodeStringTable (gIScsiControllerNameTable);
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- gIScsiControllerNameTable = NULL;
- }
- //
- // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
- // if it has been installed.
- //
- Status = gBS->HandleProtocol (
- gIScsiIp4DriverBinding.DriverBindingHandle,
- &gEfiComponentNameProtocolGuid,
- (VOID **)&ComponentName
- );
- if (!EFI_ERROR (Status)) {
- Status = gBS->UninstallMultipleProtocolInterfaces (
- gIScsiIp4DriverBinding.DriverBindingHandle,
- &gEfiComponentNameProtocolGuid,
- ComponentName,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- }
- Status = gBS->HandleProtocol (
- gIScsiIp4DriverBinding.DriverBindingHandle,
- &gEfiComponentName2ProtocolGuid,
- (VOID **)&ComponentName2
- );
- if (!EFI_ERROR (Status)) {
- gBS->UninstallMultipleProtocolInterfaces (
- gIScsiIp4DriverBinding.DriverBindingHandle,
- &gEfiComponentName2ProtocolGuid,
- ComponentName2,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- }
- //
- // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
- // if it has been installed.
- //
- Status = gBS->HandleProtocol (
- gIScsiIp6DriverBinding.DriverBindingHandle,
- &gEfiComponentNameProtocolGuid,
- (VOID **)&ComponentName
- );
- if (!EFI_ERROR (Status)) {
- Status = gBS->UninstallMultipleProtocolInterfaces (
- gIScsiIp6DriverBinding.DriverBindingHandle,
- &gEfiComponentNameProtocolGuid,
- ComponentName,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- }
- Status = gBS->HandleProtocol (
- gIScsiIp6DriverBinding.DriverBindingHandle,
- &gEfiComponentName2ProtocolGuid,
- (VOID **)&ComponentName2
- );
- if (!EFI_ERROR (Status)) {
- gBS->UninstallMultipleProtocolInterfaces (
- gIScsiIp6DriverBinding.DriverBindingHandle,
- &gEfiComponentName2ProtocolGuid,
- ComponentName2,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- }
- //
- // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- gIScsiIp4DriverBinding.DriverBindingHandle,
- &gEfiDriverBindingProtocolGuid,
- &gIScsiIp4DriverBinding,
- &gEfiIScsiInitiatorNameProtocolGuid,
- &gIScsiInitiatorName,
- NULL
- );
- if (EFI_ERROR (Status)) {
- goto ON_EXIT;
- }
- Status = gBS->UninstallMultipleProtocolInterfaces (
- gIScsiIp6DriverBinding.DriverBindingHandle,
- &gEfiDriverBindingProtocolGuid,
- &gIScsiIp6DriverBinding,
- NULL
- );
- ON_EXIT:
- if (DeviceHandleBuffer != NULL) {
- FreePool (DeviceHandleBuffer);
- }
- return Status;
- }
- /**
- This is the declaration of an EFI image entry point. This entry point is
- the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
- both device drivers and bus drivers.
- The entry point for iSCSI driver which initializes the global variables and
- installs the driver binding, component name protocol, iSCSI initiator name
- protocol and Authentication Info protocol on its image.
- @param[in] ImageHandle The firmware allocated handle for the UEFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
- **/
- EFI_STATUS
- EFIAPI
- IScsiDriverEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- EFI_ISCSI_INITIATOR_NAME_PROTOCOL *IScsiInitiatorName;
- EFI_AUTHENTICATION_INFO_PROTOCOL *AuthenticationInfo;
- //
- // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
- //
- Status = gBS->LocateProtocol (
- &gEfiIScsiInitiatorNameProtocolGuid,
- NULL,
- (VOID **)&IScsiInitiatorName
- );
- if (!EFI_ERROR (Status)) {
- return EFI_ACCESS_DENIED;
- }
- //
- // Initialize the EFI Driver Library.
- //
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gIScsiIp4DriverBinding,
- ImageHandle,
- &gIScsiComponentName,
- &gIScsiComponentName2
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gIScsiIp6DriverBinding,
- NULL,
- &gIScsiComponentName,
- &gIScsiComponentName2
- );
- if (EFI_ERROR (Status)) {
- goto Error1;
- }
- //
- // Install the iSCSI Initiator Name Protocol.
- //
- Status = gBS->InstallProtocolInterface (
- &ImageHandle,
- &gEfiIScsiInitiatorNameProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &gIScsiInitiatorName
- );
- if (EFI_ERROR (Status)) {
- goto Error2;
- }
- //
- // Create the private data structures.
- //
- IScsiCHAPInitHashList ();
- mPrivate = AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA));
- if (mPrivate == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Error3;
- }
- InitializeListHead (&mPrivate->NicInfoList);
- InitializeListHead (&mPrivate->AttemptConfigs);
- //
- // Initialize the configuration form of iSCSI.
- //
- Status = IScsiConfigFormInit (gIScsiIp4DriverBinding.DriverBindingHandle);
- if (EFI_ERROR (Status)) {
- goto Error4;
- }
- //
- // Create the Maximum Attempts.
- //
- Status = IScsiCreateAttempts (PcdGet8 (PcdMaxIScsiAttemptNumber));
- if (EFI_ERROR (Status)) {
- goto Error5;
- }
- //
- // Create Keywords for all the Attempts.
- //
- Status = IScsiCreateKeywords (PcdGet8 (PcdMaxIScsiAttemptNumber));
- if (EFI_ERROR (Status)) {
- goto Error6;
- }
- //
- // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
- // do not produce the protocol instance.
- //
- Status = gBS->LocateProtocol (
- &gEfiAuthenticationInfoProtocolGuid,
- NULL,
- (VOID **)&AuthenticationInfo
- );
- if (Status == EFI_NOT_FOUND) {
- Status = gBS->InstallProtocolInterface (
- &ImageHandle,
- &gEfiAuthenticationInfoProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &gIScsiAuthenticationInfo
- );
- if (EFI_ERROR (Status)) {
- goto Error6;
- }
- }
- return EFI_SUCCESS;
- Error6:
- IScsiCleanAttemptVariable ();
- Error5:
- IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);
- Error4:
- if (mPrivate != NULL) {
- FreePool (mPrivate);
- mPrivate = NULL;
- }
- Error3:
- gBS->UninstallMultipleProtocolInterfaces (
- ImageHandle,
- &gEfiIScsiInitiatorNameProtocolGuid,
- &gIScsiInitiatorName,
- NULL
- );
- Error2:
- EfiLibUninstallDriverBindingComponentName2 (
- &gIScsiIp6DriverBinding,
- &gIScsiComponentName,
- &gIScsiComponentName2
- );
- Error1:
- EfiLibUninstallDriverBindingComponentName2 (
- &gIScsiIp4DriverBinding,
- &gIScsiComponentName,
- &gIScsiComponentName2
- );
- return Status;
- }
|