1 /** @file
2   The entry point of IScsi driver.
3 
4 Copyright (c) 2004 - 2015, 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
9 
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.
12 
13 **/
14 
15 #include "IScsiImpl.h"
16 
17 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp4DriverBinding = {
18   IScsiIp4DriverBindingSupported,
19   IScsiIp4DriverBindingStart,
20   IScsiIp4DriverBindingStop,
21   0xa,
22   NULL,
23   NULL
24 };
25 
26 EFI_DRIVER_BINDING_PROTOCOL gIScsiIp6DriverBinding = {
27   IScsiIp6DriverBindingSupported,
28   IScsiIp6DriverBindingStart,
29   IScsiIp6DriverBindingStop,
30   0xa,
31   NULL,
32   NULL
33 };
34 
35 EFI_GUID                    gIScsiV4PrivateGuid = ISCSI_V4_PRIVATE_GUID;
36 EFI_GUID                    gIScsiV6PrivateGuid = ISCSI_V6_PRIVATE_GUID;
37 ISCSI_PRIVATE_DATA          *mPrivate           = NULL;
38 
39 /**
40   Tests to see if this driver supports the RemainingDevicePath.
41 
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
48                                    bus driver.
49 
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.
53 **/
54 EFI_STATUS
IScsiIsDevicePathSupported(IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)55 IScsiIsDevicePathSupported (
56   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
57   )
58 {
59   EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
60 
61   CurrentDevicePath = RemainingDevicePath;
62   if (CurrentDevicePath != NULL) {
63     while (!IsDevicePathEnd (CurrentDevicePath)) {
64       if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {
65         return EFI_SUCCESS;
66       }
67 
68       CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);
69     }
70 
71     return EFI_UNSUPPORTED;
72   }
73 
74   return EFI_SUCCESS;
75 }
76 
77 /**
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.
81 
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
84                                    not matched.
85 **/
86 EFI_STATUS
IScsiCheckAip()87 IScsiCheckAip (
88   )
89 {
90   UINTN                            AipHandleCount;
91   EFI_HANDLE                       *AipHandleBuffer;
92   UINTN                            AipIndex;
93   EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
94   EFI_EXT_SCSI_PASS_THRU_PROTOCOL  *ExtScsiPassThru;
95   EFI_GUID                         *InfoTypesBuffer;
96   UINTN                            InfoTypeBufferCount;
97   UINTN                            TypeIndex;
98   VOID                             *InfoBlock;
99   UINTN                            InfoBlockSize;
100   BOOLEAN                          Supported;
101   EFI_ADAPTER_INFO_NETWORK_BOOT    *NetworkBoot;
102   EFI_STATUS                       Status;
103   UINT8                            NetworkBootPolicy;
104 
105   //
106   // Check any AIP instances exist in system.
107   //
108   AipHandleCount  = 0;
109   AipHandleBuffer = NULL;
110   Status = gBS->LocateHandleBuffer (
111                   ByProtocol,
112                   &gEfiAdapterInformationProtocolGuid,
113                   NULL,
114                   &AipHandleCount,
115                   &AipHandleBuffer
116                   );
117   if (EFI_ERROR (Status) || AipHandleCount == 0) {
118     return EFI_NOT_FOUND;
119   }
120 
121   ASSERT (AipHandleBuffer != NULL);
122 
123   InfoBlock = NULL;
124 
125   for (AipIndex = 0; AipIndex < AipHandleCount; AipIndex++) {
126     Status = gBS->HandleProtocol (
127                     AipHandleBuffer[AipIndex],
128                     &gEfiAdapterInformationProtocolGuid,
129                     (VOID *) &Aip
130                     );
131     ASSERT_EFI_ERROR (Status);
132     ASSERT (Aip != NULL);
133 
134     Status = gBS->HandleProtocol (
135                     AipHandleBuffer[AipIndex],
136                     &gEfiExtScsiPassThruProtocolGuid,
137                     (VOID *) &ExtScsiPassThru
138                     );
139     if (EFI_ERROR (Status) || ExtScsiPassThru == NULL) {
140       continue;
141     }
142 
143     InfoTypesBuffer     = NULL;
144     InfoTypeBufferCount = 0;
145     Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
146     if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {
147       continue;
148     }
149     //
150     // Check whether the AIP instance has Network boot information block.
151     //
152     Supported = FALSE;
153     for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
154       if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoNetworkBootGuid)) {
155         Supported = TRUE;
156         break;
157       }
158     }
159 
160     FreePool (InfoTypesBuffer);
161     if (!Supported) {
162       continue;
163     }
164 
165     //
166     // We now have network boot information block.
167     //
168     InfoBlock     = NULL;
169     InfoBlockSize = 0;
170     Status = Aip->GetInformation (Aip, &gEfiAdapterInfoNetworkBootGuid, &InfoBlock, &InfoBlockSize);
171     if (EFI_ERROR (Status) || InfoBlock == NULL) {
172       continue;
173     }
174 
175     //
176     // Check whether the network boot policy matches.
177     //
178     NetworkBoot = (EFI_ADAPTER_INFO_NETWORK_BOOT *) InfoBlock;
179     NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);
180 
181     if (NetworkBootPolicy == STOP_UEFI_ISCSI_IF_HBA_INSTALL_AIP) {
182       Status = EFI_SUCCESS;
183       goto Exit;
184     }
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);
198       continue;
199     }
200 
201     Status = EFI_SUCCESS;
202     goto Exit;
203   }
204 
205   Status = EFI_NOT_FOUND;
206 
207 Exit:
208   if (InfoBlock != NULL) {
209     FreePool (InfoBlock);
210   }
211   if (AipHandleBuffer != NULL) {
212     FreePool (AipHandleBuffer);
213   }
214   return Status;
215 }
216 
217 /**
218   Tests to see if this driver supports a given controller. This is the worker function for
219   IScsiIp4(6)DriverBindingSupported.
220 
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
231                                    bus driver.
232   @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
233 
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
238                                    specified by This.
239   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
240                                    RemainingDevicePath is not supported by the driver specified by This.
241 **/
242 EFI_STATUS
243 EFIAPI
IScsiSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN UINT8 IpVersion)244 IScsiSupported (
245   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
246   IN EFI_HANDLE                   ControllerHandle,
247   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
248   IN UINT8                        IpVersion
249   )
250 {
251   EFI_STATUS                Status;
252   EFI_GUID                  *IScsiServiceBindingGuid;
253   EFI_GUID                  *TcpServiceBindingGuid;
254   EFI_GUID                  *DhcpServiceBindingGuid;
255 
256   if (IpVersion == IP_VERSION_4) {
257     IScsiServiceBindingGuid  = &gIScsiV4PrivateGuid;
258     TcpServiceBindingGuid    = &gEfiTcp4ServiceBindingProtocolGuid;
259     DhcpServiceBindingGuid   = &gEfiDhcp4ServiceBindingProtocolGuid;
260   } else {
261     IScsiServiceBindingGuid  = &gIScsiV6PrivateGuid;
262     TcpServiceBindingGuid    = &gEfiTcp6ServiceBindingProtocolGuid;
263     DhcpServiceBindingGuid   = &gEfiDhcp6ServiceBindingProtocolGuid;
264   }
265 
266   Status = gBS->OpenProtocol (
267                   ControllerHandle,
268                   IScsiServiceBindingGuid,
269                   NULL,
270                   This->DriverBindingHandle,
271                   ControllerHandle,
272                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
273                   );
274   if (!EFI_ERROR (Status)) {
275     return EFI_ALREADY_STARTED;
276   }
277 
278   Status = gBS->OpenProtocol (
279                   ControllerHandle,
280                   TcpServiceBindingGuid,
281                   NULL,
282                   This->DriverBindingHandle,
283                   ControllerHandle,
284                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
285                   );
286   if (EFI_ERROR (Status)) {
287     return EFI_UNSUPPORTED;
288   }
289 
290   Status = IScsiIsDevicePathSupported (RemainingDevicePath);
291   if (EFI_ERROR (Status)) {
292     return EFI_UNSUPPORTED;
293   }
294 
295   if (IScsiDhcpIsConfigured (ControllerHandle, IpVersion)) {
296     Status = gBS->OpenProtocol (
297                     ControllerHandle,
298                     DhcpServiceBindingGuid,
299                     NULL,
300                     This->DriverBindingHandle,
301                     ControllerHandle,
302                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL
303                     );
304     if (EFI_ERROR (Status)) {
305       return EFI_UNSUPPORTED;
306     }
307   }
308 
309   return EFI_SUCCESS;
310 }
311 
312 
313 /**
314   Start to manage the controller. This is the worker function for
315   IScsiIp4(6)DriverBindingStart.
316 
317   @param[in]  Image                Handle of the image.
318   @param[in]  ControllerHandle     Handle of the controller.
319   @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
320 
321   @retval EFI_SUCCES            This driver was started.
322   @retval EFI_ALREADY_STARTED   This driver is already running on this device.
323   @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
324   @retval EFI_NOT_FOUND         There is no sufficient information to establish
325                                 the iScsi session.
326   @retval EFI_DEVICE_ERROR      Failed to get TCP connection device path.
327 
328 **/
329 EFI_STATUS
IScsiStart(IN EFI_HANDLE Image,IN EFI_HANDLE ControllerHandle,IN UINT8 IpVersion)330 IScsiStart (
331   IN EFI_HANDLE                   Image,
332   IN EFI_HANDLE                   ControllerHandle,
333   IN UINT8                        IpVersion
334   )
335 {
336   EFI_STATUS                      Status;
337   ISCSI_DRIVER_DATA               *Private;
338   LIST_ENTRY                      *Entry;
339   LIST_ENTRY                      *NextEntry;
340   ISCSI_ATTEMPT_CONFIG_NVDATA     *AttemptConfigData;
341   ISCSI_SESSION                   *Session;
342   UINT8                           Index;
343   EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExistIScsiExtScsiPassThru;
344   ISCSI_DRIVER_DATA               *ExistPrivate;
345   UINT8                           *AttemptConfigOrder;
346   UINTN                           AttemptConfigOrderSize;
347   UINT8                           BootSelected;
348   EFI_HANDLE                      *HandleBuffer;
349   UINTN                           NumberOfHandles;
350   EFI_DEVICE_PATH_PROTOCOL        *DevicePath;
351   EFI_GUID                        *IScsiPrivateGuid;
352   EFI_GUID                        *TcpServiceBindingGuid;
353   CHAR16                          MacString[ISCSI_MAX_MAC_STRING_LEN];
354   BOOLEAN                         NeedUpdate;
355   VOID                            *Interface;
356   EFI_GUID                        *ProtocolGuid;
357   UINT8                           NetworkBootPolicy;
358 
359   //
360   // Test to see if iSCSI driver supports the given controller.
361   //
362 
363   if (IpVersion == IP_VERSION_4) {
364     IScsiPrivateGuid      = &gIScsiV4PrivateGuid;
365     TcpServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid;
366     ProtocolGuid          = &gEfiTcp4ProtocolGuid;
367   } else if (IpVersion == IP_VERSION_6) {
368     IScsiPrivateGuid      = &gIScsiV6PrivateGuid;
369     TcpServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid;
370     ProtocolGuid          = &gEfiTcp6ProtocolGuid;
371   } else {
372     return EFI_INVALID_PARAMETER;
373   }
374 
375   Status = gBS->OpenProtocol (
376                   ControllerHandle,
377                   IScsiPrivateGuid,
378                   NULL,
379                   Image,
380                   ControllerHandle,
381                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
382                   );
383   if (!EFI_ERROR (Status)) {
384     return EFI_ALREADY_STARTED;
385   }
386 
387   Status = gBS->OpenProtocol (
388                   ControllerHandle,
389                   TcpServiceBindingGuid,
390                   NULL,
391                   Image,
392                   ControllerHandle,
393                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
394                   );
395   if (EFI_ERROR (Status)) {
396     return EFI_UNSUPPORTED;
397   }
398 
399   NetworkBootPolicy = PcdGet8 (PcdIScsiAIPNetworkBootPolicy);
400   if (NetworkBootPolicy != ALWAYS_USE_UEFI_ISCSI_AND_IGNORE_AIP) {
401     //
402     // Check existing iSCSI AIP.
403     //
404     Status = IScsiCheckAip ();
405     if (!EFI_ERROR (Status)) {
406       //
407       // Find iSCSI AIP with specified network boot policy. return EFI_ABORTED.
408       //
409       return EFI_ABORTED;
410     }
411   }
412 
413   //
414   // Record the incoming NIC info.
415   //
416   Status = IScsiAddNic (ControllerHandle);
417   if (EFI_ERROR (Status)) {
418     return Status;
419   }
420 
421   //
422   // Create the instance private data.
423   //
424   Private = IScsiCreateDriverData (Image, ControllerHandle);
425   if (Private == NULL) {
426     return EFI_OUT_OF_RESOURCES;
427   }
428 
429   //
430   // Create a underlayer child instance, but not need to configure it. Just open ChildHandle
431   // via BY_DRIVER. That is, establishing the relationship between ControllerHandle and ChildHandle.
432   // Therefore, when DisconnectController(), especially VLAN virtual controller handle,
433   // IScsiDriverBindingStop() will be called.
434   //
435   Status = NetLibCreateServiceChild (
436              ControllerHandle,
437              Image,
438              TcpServiceBindingGuid,
439              &Private->ChildHandle
440              );
441 
442   if (EFI_ERROR (Status)) {
443     goto ON_ERROR;
444   }
445 
446   Status = gBS->OpenProtocol (
447                   Private->ChildHandle, /// Default Tcp child
448                   ProtocolGuid,
449                   &Interface,
450                   Image,
451                   ControllerHandle,
452                   EFI_OPEN_PROTOCOL_BY_DRIVER
453                   );
454 
455   if (EFI_ERROR (Status)) {
456     goto ON_ERROR;
457   }
458 
459   //
460   // Always install private protocol no matter what happens later. We need to
461   // keep the relationship between ControllerHandle and ChildHandle.
462   //
463   Status = gBS->InstallProtocolInterface (
464                   &ControllerHandle,
465                   IScsiPrivateGuid,
466                   EFI_NATIVE_INTERFACE,
467                   &Private->IScsiIdentifier
468                   );
469   if (EFI_ERROR (Status)) {
470     goto ON_ERROR;
471   }
472 
473   if (IpVersion == IP_VERSION_4) {
474     mPrivate->Ipv6Flag = FALSE;
475   } else {
476     mPrivate->Ipv6Flag = TRUE;
477   }
478 
479   //
480   // Get the current iSCSI configuration data.
481   //
482   Status = IScsiGetConfigData (Private);
483   if (EFI_ERROR (Status)) {
484     goto ON_ERROR;
485   }
486 
487   //
488   // If there is already a successul attempt, check whether this attempt is the
489   // first "enabled for MPIO" attempt. If not, still try the first attempt.
490   // In single path mode, try all attempts.
491   //
492   ExistPrivate = NULL;
493   Status       = EFI_NOT_FOUND;
494 
495   if (mPrivate->OneSessionEstablished && mPrivate->EnableMpio) {
496     AttemptConfigData = NULL;
497     NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) {
498      AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
499       if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
500         break;
501       }
502     }
503 
504     if (AttemptConfigData == NULL) {
505       goto ON_ERROR;
506     }
507 
508     if (AttemptConfigData->AttemptConfigIndex == mPrivate->BootSelectedIndex) {
509       goto ON_EXIT;
510     }
511 
512     //
513     // Uninstall the original ExtScsiPassThru first.
514     //
515 
516     //
517     // Locate all ExtScsiPassThru protocol instances.
518     //
519     Status = gBS->LocateHandleBuffer (
520                     ByProtocol,
521                     &gEfiExtScsiPassThruProtocolGuid,
522                     NULL,
523                     &NumberOfHandles,
524                     &HandleBuffer
525                     );
526     if (EFI_ERROR (Status)) {
527       goto ON_ERROR;
528     }
529 
530     //
531     // Find ExtScsiPassThru protocol instance produced by this driver.
532     //
533     ExistIScsiExtScsiPassThru = NULL;
534     for (Index = 0; Index < NumberOfHandles && ExistIScsiExtScsiPassThru == NULL; Index++) {
535       Status = gBS->HandleProtocol (
536                       HandleBuffer[Index],
537                       &gEfiDevicePathProtocolGuid,
538                       (VOID **) &DevicePath
539                       );
540       if (EFI_ERROR (Status)) {
541         continue;
542       }
543 
544       while (!IsDevicePathEnd (DevicePath)) {
545         if ((DevicePath->Type == MESSAGING_DEVICE_PATH) && (DevicePath->SubType == MSG_MAC_ADDR_DP)) {
546           //
547           // Get the ExtScsiPassThru protocol instance.
548           //
549           Status = gBS->HandleProtocol (
550                           HandleBuffer[Index],
551                           &gEfiExtScsiPassThruProtocolGuid,
552                           (VOID **) &ExistIScsiExtScsiPassThru
553                           );
554           ASSERT_EFI_ERROR (Status);
555           break;
556         }
557 
558         DevicePath = NextDevicePathNode (DevicePath);
559       }
560     }
561 
562     FreePool (HandleBuffer);
563 
564     if (ExistIScsiExtScsiPassThru == NULL) {
565       Status = EFI_NOT_FOUND;
566       goto ON_ERROR;
567     }
568 
569     ExistPrivate = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (ExistIScsiExtScsiPassThru);
570 
571     Status = gBS->UninstallProtocolInterface (
572                     ExistPrivate->ExtScsiPassThruHandle,
573                     &gEfiExtScsiPassThruProtocolGuid,
574                     &ExistPrivate->IScsiExtScsiPassThru
575                     );
576     if (EFI_ERROR (Status)) {
577       goto ON_ERROR;
578     }
579   }
580 
581   //
582   // Install the Ext SCSI PASS THRU protocol.
583   //
584   Status = gBS->InstallProtocolInterface (
585                   &Private->ExtScsiPassThruHandle,
586                   &gEfiExtScsiPassThruProtocolGuid,
587                   EFI_NATIVE_INTERFACE,
588                   &Private->IScsiExtScsiPassThru
589                   );
590   if (EFI_ERROR (Status)) {
591     goto ON_ERROR;
592   }
593 
594   BootSelected = 0;
595 
596   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
597     AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
598     //
599     // Don't process the attempt that does not associate with the current NIC or
600     // this attempt is disabled or established.
601     //
602     if (AttemptConfigData->NicIndex != mPrivate->CurrentNic ||
603         AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED ||
604         AttemptConfigData->ValidPath) {
605       continue;
606     }
607 
608     //
609     // In multipath mode, don't process attempts configured for single path.
610     // In default single path mode, don't process attempts configured for multipath.
611     //
612     if ((mPrivate->EnableMpio &&
613          AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED_FOR_MPIO) ||
614         (!mPrivate->EnableMpio &&
615          AttemptConfigData->SessionConfigData.Enabled != ISCSI_ENABLED)) {
616       continue;
617     }
618 
619     //
620     // Don't process the attempt that fails to get the init/target information from DHCP.
621     //
622     if (AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp &&
623         !AttemptConfigData->DhcpSuccess) {
624       if (!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount > 0) {
625         mPrivate->ValidSinglePathCount--;
626       }
627       continue;
628     }
629 
630     //
631     // Don't process the autoconfigure path if it is already established.
632     //
633     if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
634         AttemptConfigData->AutoConfigureSuccess) {
635       continue;
636     }
637 
638     //
639     // Don't process the attempt if its IP mode is not in the current IP version.
640     //
641     if (!mPrivate->Ipv6Flag) {
642       if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
643         continue;
644       }
645       if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
646           AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {
647         continue;
648       }
649     } else {
650       if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
651         continue;
652       }
653       if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
654           AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {
655         continue;
656       }
657     }
658 
659     //
660     // Fill in the Session and init it.
661     //
662     Session = (ISCSI_SESSION *) AllocateZeroPool (sizeof (ISCSI_SESSION));
663     if (Session == NULL) {
664       Status = EFI_OUT_OF_RESOURCES;
665       goto ON_ERROR;
666     }
667 
668     Session->Private    = Private;
669     Session->ConfigData = AttemptConfigData;
670     Session->AuthType   = AttemptConfigData->AuthenticationType;
671 
672     AsciiStrToUnicodeStr (AttemptConfigData->MacString, MacString);
673     UnicodeSPrint (
674       mPrivate->PortString,
675       (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
676       L"%s%d",
677       MacString,
678       (UINTN) AttemptConfigData->AttemptConfigIndex
679       );
680 
681     if (Session->AuthType == ISCSI_AUTH_TYPE_CHAP) {
682       Session->AuthData.CHAP.AuthConfig = &AttemptConfigData->AuthConfigData.CHAP;
683     }
684 
685     IScsiSessionInit (Session, FALSE);
686 
687     //
688     // Try to login and create an iSCSI session according to the configuration.
689     //
690     Status = IScsiSessionLogin (Session);
691     if (Status == EFI_MEDIA_CHANGED) {
692       //
693       // The specified target is not available, and the redirection information is
694       // received. Login the session again with the updated target address.
695       //
696       Status = IScsiSessionLogin (Session);
697     } else if (Status == EFI_NOT_READY) {
698       Status = IScsiSessionReLogin (Session);
699     }
700 
701     if (EFI_ERROR (Status)) {
702       //
703       // In Single path mode, only the successful attempt will be recorded in iBFT;
704       // in multi-path mode, all the attempt entries in MPIO will be recorded in iBFT.
705       //
706       if (!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount > 0) {
707         mPrivate->ValidSinglePathCount--;
708       }
709 
710       FreePool (Session);
711 
712     } else {
713       AttemptConfigData->ValidPath = TRUE;
714 
715       //
716       // Do not record the attempt in iBFT if it login with KRB5.
717       // TODO: record KRB5 attempt information in the iSCSI device path.
718       //
719       if (Session->AuthType == ISCSI_AUTH_TYPE_KRB) {
720         if (!mPrivate->EnableMpio && mPrivate->ValidSinglePathCount > 0) {
721           mPrivate->ValidSinglePathCount--;
722         }
723 
724         AttemptConfigData->ValidiBFTPath = FALSE;
725       } else {
726         AttemptConfigData->ValidiBFTPath = TRUE;
727       }
728 
729       //
730       // IScsi session success. Update the attempt state to NVR.
731       //
732       if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
733         AttemptConfigData->AutoConfigureSuccess = TRUE;
734       }
735 
736       gRT->SetVariable (
737              mPrivate->PortString,
738              &gEfiIScsiInitiatorNameProtocolGuid,
739              ISCSI_CONFIG_VAR_ATTR,
740              sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
741              AttemptConfigData
742              );
743 
744       //
745       // Select the first login session. Abort others.
746       //
747       if (Private->Session == NULL) {
748         Private->Session = Session;
749         BootSelected     = AttemptConfigData->AttemptConfigIndex;
750         //
751         // Don't validate other attempt in multipath mode if one is success.
752         //
753         if (mPrivate->EnableMpio) {
754           break;
755         }
756       } else {
757         IScsiSessionAbort (Session);
758         FreePool (Session);
759       }
760     }
761   }
762 
763   //
764   // All attempts configured for this driver instance are not valid.
765   //
766   if (Private->Session == NULL) {
767     Status = gBS->UninstallProtocolInterface (
768                     Private->ExtScsiPassThruHandle,
769                     &gEfiExtScsiPassThruProtocolGuid,
770                     &Private->IScsiExtScsiPassThru
771                     );
772     ASSERT_EFI_ERROR (Status);
773     Private->ExtScsiPassThruHandle = NULL;
774 
775     //
776     // Reinstall the original ExtScsiPassThru back.
777     //
778     if (mPrivate->OneSessionEstablished && ExistPrivate != NULL) {
779       Status = gBS->InstallProtocolInterface (
780                       &ExistPrivate->ExtScsiPassThruHandle,
781                       &gEfiExtScsiPassThruProtocolGuid,
782                       EFI_NATIVE_INTERFACE,
783                       &ExistPrivate->IScsiExtScsiPassThru
784                       );
785       if (EFI_ERROR (Status)) {
786         goto ON_ERROR;
787       }
788 
789       goto ON_EXIT;
790     }
791 
792     Status = EFI_NOT_FOUND;
793 
794     goto ON_ERROR;
795   }
796 
797   NeedUpdate = TRUE;
798   //
799   // More than one attempt successes.
800   //
801   if (Private->Session != NULL && mPrivate->OneSessionEstablished) {
802 
803     AttemptConfigOrder = IScsiGetVariableAndSize (
804                            L"AttemptOrder",
805                            &gIScsiConfigGuid,
806                            &AttemptConfigOrderSize
807                            );
808     if (AttemptConfigOrder == NULL) {
809       goto ON_ERROR;
810     }
811     for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
812       if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex ||
813           AttemptConfigOrder[Index] == BootSelected) {
814         break;
815       }
816     }
817 
818     if (mPrivate->EnableMpio) {
819       //
820       // Use the attempt in earlier order. Abort the later one in MPIO.
821       //
822       if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {
823         IScsiSessionAbort (Private->Session);
824         FreePool (Private->Session);
825         Private->Session = NULL;
826         gBS->UninstallProtocolInterface (
827                Private->ExtScsiPassThruHandle,
828                &gEfiExtScsiPassThruProtocolGuid,
829                &Private->IScsiExtScsiPassThru
830                );
831         Private->ExtScsiPassThruHandle = NULL;
832 
833         //
834         // Reinstall the original ExtScsiPassThru back.
835         //
836         Status = gBS->InstallProtocolInterface (
837                         &ExistPrivate->ExtScsiPassThruHandle,
838                         &gEfiExtScsiPassThruProtocolGuid,
839                         EFI_NATIVE_INTERFACE,
840                         &ExistPrivate->IScsiExtScsiPassThru
841                         );
842         if (EFI_ERROR (Status)) {
843           goto ON_ERROR;
844         }
845 
846         goto ON_EXIT;
847       } else {
848         if (AttemptConfigOrder[Index] != BootSelected) {
849           goto ON_ERROR;
850         }
851         mPrivate->BootSelectedIndex = BootSelected;
852         //
853         // Clear the resource in ExistPrivate.
854         //
855         gBS->UninstallProtocolInterface (
856                ExistPrivate->Controller,
857                IScsiPrivateGuid,
858                &ExistPrivate->IScsiIdentifier
859                );
860 
861         IScsiRemoveNic (ExistPrivate->Controller);
862         if (ExistPrivate->Session != NULL) {
863           IScsiSessionAbort (ExistPrivate->Session);
864         }
865 
866         IScsiCleanDriverData (ExistPrivate);
867       }
868     } else {
869       //
870       // Use the attempt in earlier order as boot selected in single path mode.
871       //
872       if (AttemptConfigOrder[Index] == mPrivate->BootSelectedIndex) {
873         NeedUpdate = FALSE;
874       }
875     }
876 
877   }
878 
879   if (NeedUpdate) {
880     mPrivate->OneSessionEstablished = TRUE;
881     mPrivate->BootSelectedIndex     = BootSelected;
882   }
883 
884   //
885   // Duplicate the Session's tcp connection device path. The source port field
886   // will be set to zero as one iSCSI session is comprised of several iSCSI
887   // connections.
888   //
889   Private->DevicePath = IScsiGetTcpConnDevicePath (Private->Session);
890   if (Private->DevicePath == NULL) {
891     Status = EFI_DEVICE_ERROR;
892     goto ON_ERROR;
893   }
894   //
895   // Install the updated device path onto the ExtScsiPassThruHandle.
896   //
897   Status = gBS->InstallProtocolInterface (
898                   &Private->ExtScsiPassThruHandle,
899                   &gEfiDevicePathProtocolGuid,
900                   EFI_NATIVE_INTERFACE,
901                   Private->DevicePath
902                   );
903   if (EFI_ERROR (Status)) {
904     goto ON_ERROR;
905   }
906 
907   //
908   // ISCSI children should share the default Tcp child, just open the default Tcp child via BY_CHILD_CONTROLLER.
909   //
910   Status = gBS->OpenProtocol (
911                   Private->ChildHandle, /// Default Tcp child
912                   ProtocolGuid,
913                   &Interface,
914                   Image,
915                   Private->ExtScsiPassThruHandle,
916                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
917                   );
918   if (EFI_ERROR (Status)) {
919     gBS->UninstallMultipleProtocolInterfaces (
920            Private->ExtScsiPassThruHandle,
921            &gEfiExtScsiPassThruProtocolGuid,
922            &Private->IScsiExtScsiPassThru,
923            &gEfiDevicePathProtocolGuid,
924            Private->DevicePath,
925            NULL
926            );
927 
928     goto ON_ERROR;
929   }
930 
931 ON_EXIT:
932 
933   //
934   // Update/Publish the iSCSI Boot Firmware Table.
935   //
936   if (mPrivate->BootSelectedIndex != 0) {
937     IScsiPublishIbft ();
938   }
939 
940   return EFI_SUCCESS;
941 
942 ON_ERROR:
943 
944   if (Private->Session != NULL) {
945     IScsiSessionAbort (Private->Session);
946   }
947 
948   return Status;
949 }
950 
951 /**
952   Stops a device controller or a bus controller. This is the worker function for
953   IScsiIp4(6)DriverBindingStop.
954 
955   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
956   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
957                                 support a bus specific I/O protocol for the driver
958                                 to use to stop the device.
959   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
960   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
961                                 if NumberOfChildren is 0.
962   @param[in]  IpVersion         IP_VERSION_4 or IP_VERSION_6.
963 
964   @retval EFI_SUCCESS           The device was stopped.
965   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
966 
967 **/
968 EFI_STATUS
969 EFIAPI
IScsiStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL,IN UINT8 IpVersion)970 IScsiStop (
971   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
972   IN EFI_HANDLE                   ControllerHandle,
973   IN UINTN                        NumberOfChildren,
974   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL,
975   IN UINT8                        IpVersion
976   )
977 {
978   EFI_HANDLE                      IScsiController;
979   EFI_STATUS                      Status;
980   ISCSI_PRIVATE_PROTOCOL          *IScsiIdentifier;
981   ISCSI_DRIVER_DATA               *Private;
982   EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
983   ISCSI_CONNECTION                *Conn;
984   EFI_GUID                        *ProtocolGuid;
985   EFI_GUID                        *TcpServiceBindingGuid;
986   EFI_GUID                        *TcpProtocolGuid;
987 
988 
989   if (NumberOfChildren != 0) {
990     //
991     // We should have only one child.
992     //
993     Status = gBS->OpenProtocol (
994                     ChildHandleBuffer[0],
995                     &gEfiExtScsiPassThruProtocolGuid,
996                     (VOID **) &PassThru,
997                     This->DriverBindingHandle,
998                     ControllerHandle,
999                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
1000                     );
1001     if (EFI_ERROR (Status)) {
1002       return EFI_DEVICE_ERROR;
1003     }
1004 
1005     Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
1006     Conn    = NET_LIST_HEAD (&Private->Session->Conns, ISCSI_CONNECTION, Link);
1007 
1008     //
1009     // Previously the TCP protocol is opened BY_CHILD_CONTROLLER. Just close
1010     // the protocol here, but do not uninstall the device path protocol and
1011     // EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
1012     //
1013     if (IpVersion == IP_VERSION_4) {
1014       ProtocolGuid = &gEfiTcp4ProtocolGuid;
1015     } else {
1016       ProtocolGuid = &gEfiTcp6ProtocolGuid;
1017     }
1018 
1019     gBS->CloseProtocol (
1020            Private->ChildHandle,
1021            ProtocolGuid,
1022            Private->Image,
1023            Private->ExtScsiPassThruHandle
1024            );
1025 
1026     gBS->CloseProtocol (
1027            Conn->TcpIo.Handle,
1028            ProtocolGuid,
1029            Private->Image,
1030            Private->ExtScsiPassThruHandle
1031            );
1032 
1033     return EFI_SUCCESS;
1034   }
1035 
1036   //
1037   // Get the handle of the controller we are controling.
1038   //
1039   if (IpVersion == IP_VERSION_4) {
1040     ProtocolGuid            = &gIScsiV4PrivateGuid;
1041     TcpProtocolGuid         = &gEfiTcp4ProtocolGuid;
1042     TcpServiceBindingGuid   = &gEfiTcp4ServiceBindingProtocolGuid;
1043   } else {
1044     ProtocolGuid            = &gIScsiV6PrivateGuid;
1045     TcpProtocolGuid         = &gEfiTcp6ProtocolGuid;
1046     TcpServiceBindingGuid   = &gEfiTcp6ServiceBindingProtocolGuid;
1047   }
1048   IScsiController = NetLibGetNicHandle (ControllerHandle, TcpProtocolGuid);
1049   if (IScsiController == NULL) {
1050     return EFI_SUCCESS;
1051   }
1052 
1053   Status = gBS->OpenProtocol (
1054                   IScsiController,
1055                   ProtocolGuid,
1056                   (VOID **) &IScsiIdentifier,
1057                   This->DriverBindingHandle,
1058                   ControllerHandle,
1059                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1060                   );
1061   if (EFI_ERROR (Status)) {
1062     return EFI_DEVICE_ERROR;
1063   }
1064 
1065   Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
1066   ASSERT (Private != NULL);
1067 
1068   if (Private->ChildHandle != NULL) {
1069     Status = gBS->CloseProtocol (
1070                     Private->ChildHandle,
1071                     TcpProtocolGuid,
1072                     This->DriverBindingHandle,
1073                     IScsiController
1074                     );
1075 
1076     ASSERT (!EFI_ERROR (Status));
1077 
1078     Status = NetLibDestroyServiceChild (
1079                IScsiController,
1080                This->DriverBindingHandle,
1081                TcpServiceBindingGuid,
1082                Private->ChildHandle
1083                );
1084 
1085     ASSERT (!EFI_ERROR (Status));
1086   }
1087 
1088   gBS->UninstallProtocolInterface (
1089          IScsiController,
1090          ProtocolGuid,
1091          &Private->IScsiIdentifier
1092          );
1093 
1094   //
1095   // Remove this NIC.
1096   //
1097   IScsiRemoveNic (IScsiController);
1098 
1099   //
1100   // Update the iSCSI Boot Firware Table.
1101   //
1102   IScsiPublishIbft ();
1103 
1104   if (Private->Session != NULL) {
1105     IScsiSessionAbort (Private->Session);
1106   }
1107 
1108   IScsiCleanDriverData (Private);
1109 
1110   return EFI_SUCCESS;
1111 }
1112 
1113 /**
1114   Tests to see if this driver supports a given controller. If a child device is provided,
1115   it tests to see if this driver supports creating a handle for the specified child device.
1116 
1117   This function checks to see if the driver specified by This supports the device specified by
1118   ControllerHandle. Drivers typically use the device path attached to
1119   ControllerHandle and/or the services from the bus I/O abstraction attached to
1120   ControllerHandle to determine if the driver supports ControllerHandle. This function
1121   may be called many times during platform initialization. In order to reduce boot times, the tests
1122   performed by this function must be very small and take as little time as possible to execute. This
1123   function must not change the state of any hardware devices, and this function must be aware that the
1124   device specified by ControllerHandle may already be managed by the same driver or a
1125   different driver. This function must match its calls to AllocatePages() with FreePages(),
1126   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1127   Since ControllerHandle may have been previously started by the same driver, if a protocol is
1128   already in the opened state, then it must not be closed with CloseProtocol(). This is required
1129   to guarantee the state of ControllerHandle is not modified by this function.
1130 
1131   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1132   @param[in]  ControllerHandle     The handle of the controller to test. This handle
1133                                    must support a protocol interface that supplies
1134                                    an I/O abstraction to the driver.
1135   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
1136                                    parameter is ignored by device drivers, and is optional for bus
1137                                    drivers. For bus drivers, if this parameter is not NULL, then
1138                                    the bus driver must determine if the bus controller specified
1139                                    by ControllerHandle and the child controller specified
1140                                    by RemainingDevicePath are both supported by this
1141                                    bus driver.
1142 
1143   @retval EFI_SUCCESS              The device specified by ControllerHandle and
1144                                    RemainingDevicePath is supported by the driver specified by This.
1145   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
1146                                    RemainingDevicePath is already managed by the driver
1147                                    specified by This.
1148   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
1149                                    RemainingDevicePath is already managed by a different
1150                                    driver or an application that requires exclusive access.
1151                                    Currently not implemented.
1152   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
1153                                    RemainingDevicePath is not supported by the driver specified by This.
1154 **/
1155 EFI_STATUS
1156 EFIAPI
IScsiIp4DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1157 IScsiIp4DriverBindingSupported (
1158   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1159   IN EFI_HANDLE                   ControllerHandle,
1160   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1161   )
1162 {
1163   return IScsiSupported (
1164            This,
1165            ControllerHandle,
1166            RemainingDevicePath,
1167            IP_VERSION_4
1168            );
1169 }
1170 
1171 /**
1172   Starts a device controller or a bus controller.
1173 
1174   The Start() function is designed to be invoked from the EFI boot service ConnectController().
1175   As a result, much of the error checking on the parameters to Start() has been moved into this
1176   common boot service. It is legal to call Start() from other locations,
1177   but the following calling restrictions must be followed or the system behavior will not be deterministic.
1178   1. ControllerHandle must be a valid EFI_HANDLE.
1179   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1180      EFI_DEVICE_PATH_PROTOCOL.
1181   3. Prior to calling Start(), the Supported() function for the driver specified by This must
1182      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1183 
1184   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1185   @param[in]  ControllerHandle     The handle of the controller to start. This handle
1186                                    must support a protocol interface that supplies
1187                                    an I/O abstraction to the driver.
1188   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
1189                                    parameter is ignored by device drivers, and is optional for bus
1190                                    drivers. For a bus driver, if this parameter is NULL, then handles
1191                                    for all the children of Controller are created by this driver.
1192                                    If this parameter is not NULL and the first Device Path Node is
1193                                    not the End of Device Path Node, then only the handle for the
1194                                    child device specified by the first Device Path Node of
1195                                    RemainingDevicePath is created by this driver.
1196                                    If the first Device Path Node of RemainingDevicePath is
1197                                    the End of Device Path Node, no child handle is created by this
1198                                    driver.
1199 
1200   @retval EFI_SUCCESS              The device was started.
1201   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error. Currently not implemented.
1202   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
1203   @retval Others                   The driver failed to start the device.
1204 
1205 **/
1206 EFI_STATUS
1207 EFIAPI
IScsiIp4DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1208 IScsiIp4DriverBindingStart (
1209   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1210   IN EFI_HANDLE                   ControllerHandle,
1211   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1212   )
1213 {
1214   EFI_STATUS        Status;
1215 
1216   Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_4);
1217   if (Status == EFI_ALREADY_STARTED) {
1218     Status = EFI_SUCCESS;
1219   }
1220 
1221   return Status;
1222 }
1223 
1224 /**
1225   Stops a device controller or a bus controller.
1226 
1227   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1228   As a result, much of the error checking on the parameters to Stop() has been moved
1229   into this common boot service. It is legal to call Stop() from other locations,
1230   but the following calling restrictions must be followed or the system behavior will not be deterministic.
1231   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1232      same driver's Start() function.
1233   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1234      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1235      Start() function, and the Start() function must have called OpenProtocol() on
1236      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1237 
1238   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1239   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
1240                                 support a bus specific I/O protocol for the driver
1241                                 to use to stop the device.
1242   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
1243   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
1244                                 if NumberOfChildren is 0.
1245 
1246   @retval EFI_SUCCESS           The device was stopped.
1247   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
1248 
1249 **/
1250 EFI_STATUS
1251 EFIAPI
IScsiIp4DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)1252 IScsiIp4DriverBindingStop (
1253   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1254   IN EFI_HANDLE                   ControllerHandle,
1255   IN UINTN                        NumberOfChildren,
1256   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
1257   )
1258 {
1259   return IScsiStop (
1260            This,
1261            ControllerHandle,
1262            NumberOfChildren,
1263            ChildHandleBuffer,
1264            IP_VERSION_4
1265            );
1266 }
1267 
1268 /**
1269   Tests to see if this driver supports a given controller. If a child device is provided,
1270   it tests to see if this driver supports creating a handle for the specified child device.
1271 
1272   This function checks to see if the driver specified by This supports the device specified by
1273   ControllerHandle. Drivers typically use the device path attached to
1274   ControllerHandle and/or the services from the bus I/O abstraction attached to
1275   ControllerHandle to determine if the driver supports ControllerHandle. This function
1276   may be called many times during platform initialization. In order to reduce boot times, the tests
1277   performed by this function must be very small and take as little time as possible to execute. This
1278   function must not change the state of any hardware devices, and this function must be aware that the
1279   device specified by ControllerHandle may already be managed by the same driver or a
1280   different driver. This function must match its calls to AllocatePages() with FreePages(),
1281   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
1282   Since ControllerHandle may have been previously started by the same driver, if a protocol is
1283   already in the opened state, then it must not be closed with CloseProtocol(). This is required
1284   to guarantee the state of ControllerHandle is not modified by this function.
1285 
1286   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1287   @param[in]  ControllerHandle     The handle of the controller to test. This handle
1288                                    must support a protocol interface that supplies
1289                                    an I/O abstraction to the driver.
1290   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
1291                                    parameter is ignored by device drivers, and is optional for bus
1292                                    drivers. For bus drivers, if this parameter is not NULL, then
1293                                    the bus driver must determine if the bus controller specified
1294                                    by ControllerHandle and the child controller specified
1295                                    by RemainingDevicePath are both supported by this
1296                                    bus driver.
1297 
1298   @retval EFI_SUCCESS              The device specified by ControllerHandle and
1299                                    RemainingDevicePath is supported by the driver specified by This.
1300   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
1301                                    RemainingDevicePath is already managed by the driver
1302                                    specified by This.
1303   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
1304                                    RemainingDevicePath is already managed by a different
1305                                    driver or an application that requires exclusive access.
1306                                    Currently not implemented.
1307   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
1308                                    RemainingDevicePath is not supported by the driver specified by This.
1309 **/
1310 EFI_STATUS
1311 EFIAPI
IScsiIp6DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1312 IScsiIp6DriverBindingSupported (
1313   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1314   IN EFI_HANDLE                   ControllerHandle,
1315   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1316   )
1317 {
1318   return IScsiSupported (
1319            This,
1320            ControllerHandle,
1321            RemainingDevicePath,
1322            IP_VERSION_6
1323            );
1324 }
1325 
1326 /**
1327   Starts a device controller or a bus controller.
1328 
1329   The Start() function is designed to be invoked from the EFI boot service ConnectController().
1330   As a result, much of the error checking on the parameters to Start() has been moved into this
1331   common boot service. It is legal to call Start() from other locations,
1332   but the following calling restrictions must be followed or the system behavior will not be deterministic.
1333   1. ControllerHandle must be a valid EFI_HANDLE.
1334   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
1335      EFI_DEVICE_PATH_PROTOCOL.
1336   3. Prior to calling Start(), the Supported() function for the driver specified by This must
1337      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
1338 
1339   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1340   @param[in]  ControllerHandle     The handle of the controller to start. This handle
1341                                    must support a protocol interface that supplies
1342                                    an I/O abstraction to the driver.
1343   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
1344                                    parameter is ignored by device drivers, and is optional for bus
1345                                    drivers. For a bus driver, if this parameter is NULL, then handles
1346                                    for all the children of Controller are created by this driver.
1347                                    If this parameter is not NULL and the first Device Path Node is
1348                                    not the End of Device Path Node, then only the handle for the
1349                                    child device specified by the first Device Path Node of
1350                                    RemainingDevicePath is created by this driver.
1351                                    If the first Device Path Node of RemainingDevicePath is
1352                                    the End of Device Path Node, no child handle is created by this
1353                                    driver.
1354 
1355   @retval EFI_SUCCESS              The device was started.
1356   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error. Currently not implemented.
1357   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
1358   @retval Others                   The driver failed to start the device.
1359 
1360 **/
1361 EFI_STATUS
1362 EFIAPI
IScsiIp6DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1363 IScsiIp6DriverBindingStart (
1364   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1365   IN EFI_HANDLE                   ControllerHandle,
1366   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1367   )
1368 {
1369   EFI_STATUS        Status;
1370 
1371   Status = IScsiStart (This->DriverBindingHandle, ControllerHandle, IP_VERSION_6);
1372   if (Status == EFI_ALREADY_STARTED) {
1373     Status = EFI_SUCCESS;
1374   }
1375 
1376   return Status;
1377 }
1378 
1379 /**
1380   Stops a device controller or a bus controller.
1381 
1382   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1383   As a result, much of the error checking on the parameters to Stop() has been moved
1384   into this common boot service. It is legal to call Stop() from other locations,
1385   but the following calling restrictions must be followed or the system behavior will not be deterministic.
1386   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1387      same driver's Start() function.
1388   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1389      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1390      Start() function, and the Start() function must have called OpenProtocol() on
1391      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1392 
1393   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1394   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
1395                                 support a bus specific I/O protocol for the driver
1396                                 to use to stop the device.
1397   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
1398   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
1399                                 if NumberOfChildren is 0.
1400 
1401   @retval EFI_SUCCESS           The device was stopped.
1402   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
1403 
1404 **/
1405 EFI_STATUS
1406 EFIAPI
IScsiIp6DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)1407 IScsiIp6DriverBindingStop (
1408   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1409   IN EFI_HANDLE                   ControllerHandle,
1410   IN UINTN                        NumberOfChildren,
1411   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
1412   )
1413 {
1414   return IScsiStop (
1415            This,
1416            ControllerHandle,
1417            NumberOfChildren,
1418            ChildHandleBuffer,
1419            IP_VERSION_6
1420            );
1421 }
1422 
1423 /**
1424   Unload the iSCSI driver.
1425 
1426   @param[in]  ImageHandle          The handle of the driver image.
1427 
1428   @retval     EFI_SUCCESS          The driver is unloaded.
1429   @retval     EFI_DEVICE_ERROR     An unexpected error occurred.
1430 
1431 **/
1432 EFI_STATUS
1433 EFIAPI
IScsiUnload(IN EFI_HANDLE ImageHandle)1434 IScsiUnload (
1435   IN EFI_HANDLE  ImageHandle
1436   )
1437 {
1438   EFI_STATUS                        Status;
1439   UINTN                             DeviceHandleCount;
1440   EFI_HANDLE                        *DeviceHandleBuffer;
1441   UINTN                             Index;
1442   EFI_COMPONENT_NAME_PROTOCOL       *ComponentName;
1443   EFI_COMPONENT_NAME2_PROTOCOL      *ComponentName2;
1444 
1445   //
1446   // Try to disonnect the driver from the devices it's controlling.
1447   //
1448   Status = gBS->LocateHandleBuffer (
1449                   AllHandles,
1450                   NULL,
1451                   NULL,
1452                   &DeviceHandleCount,
1453                   &DeviceHandleBuffer
1454                   );
1455   if (EFI_ERROR (Status)) {
1456     return Status;
1457   }
1458 
1459   //
1460   // Disconnect the iSCSI4 driver from the controlled device.
1461   //
1462   for (Index = 0; Index < DeviceHandleCount; Index++) {
1463     Status = IScsiTestManagedDevice (
1464                DeviceHandleBuffer[Index],
1465                gIScsiIp4DriverBinding.DriverBindingHandle,
1466                &gEfiTcp4ProtocolGuid)
1467                ;
1468     if (EFI_ERROR (Status)) {
1469       continue;
1470     }
1471     Status = gBS->DisconnectController (
1472                     DeviceHandleBuffer[Index],
1473                     gIScsiIp4DriverBinding.DriverBindingHandle,
1474                     NULL
1475                     );
1476     if (EFI_ERROR (Status)) {
1477       goto ON_EXIT;
1478     }
1479   }
1480 
1481   //
1482   // Disconnect the iSCSI6 driver from the controlled device.
1483   //
1484   for (Index = 0; Index < DeviceHandleCount; Index++) {
1485     Status = IScsiTestManagedDevice (
1486                DeviceHandleBuffer[Index],
1487                gIScsiIp6DriverBinding.DriverBindingHandle,
1488                &gEfiTcp6ProtocolGuid
1489                );
1490     if (EFI_ERROR (Status)) {
1491       continue;
1492     }
1493     Status = gBS->DisconnectController (
1494                     DeviceHandleBuffer[Index],
1495                     gIScsiIp6DriverBinding.DriverBindingHandle,
1496                     NULL
1497                     );
1498     if (EFI_ERROR (Status)) {
1499       goto ON_EXIT;
1500     }
1501   }
1502 
1503   //
1504   // Unload the iSCSI configuration form.
1505   //
1506   Status = IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);
1507   if (EFI_ERROR (Status)) {
1508     goto ON_EXIT;
1509   }
1510 
1511   //
1512   // Uninstall the protocols installed by iSCSI driver.
1513   //
1514   Status = gBS->UninstallMultipleProtocolInterfaces (
1515                   ImageHandle,
1516                   &gEfiAuthenticationInfoProtocolGuid,
1517                   &gIScsiAuthenticationInfo,
1518                   NULL
1519                   );
1520   if (EFI_ERROR (Status)) {
1521     goto ON_EXIT;
1522   }
1523 
1524   if (gIScsiControllerNameTable!= NULL) {
1525     Status = FreeUnicodeStringTable (gIScsiControllerNameTable);
1526     if (EFI_ERROR (Status)) {
1527       goto ON_EXIT;
1528     }
1529     gIScsiControllerNameTable = NULL;
1530   }
1531 
1532   //
1533   // Uninstall the ComponentName and ComponentName2 protocol from iSCSI4 driver binding handle
1534   // if it has been installed.
1535   //
1536   Status = gBS->HandleProtocol (
1537                   gIScsiIp4DriverBinding.DriverBindingHandle,
1538                   &gEfiComponentNameProtocolGuid,
1539                   (VOID **) &ComponentName
1540                   );
1541   if (!EFI_ERROR (Status)) {
1542     Status = gBS->UninstallMultipleProtocolInterfaces (
1543            gIScsiIp4DriverBinding.DriverBindingHandle,
1544            &gEfiComponentNameProtocolGuid,
1545            ComponentName,
1546            NULL
1547            );
1548     if (EFI_ERROR (Status)) {
1549       goto ON_EXIT;
1550     }
1551   }
1552 
1553   Status = gBS->HandleProtocol (
1554                   gIScsiIp4DriverBinding.DriverBindingHandle,
1555                   &gEfiComponentName2ProtocolGuid,
1556                   (VOID **) &ComponentName2
1557                   );
1558   if (!EFI_ERROR (Status)) {
1559     gBS->UninstallMultipleProtocolInterfaces (
1560            gIScsiIp4DriverBinding.DriverBindingHandle,
1561            &gEfiComponentName2ProtocolGuid,
1562            ComponentName2,
1563            NULL
1564            );
1565     if (EFI_ERROR (Status)) {
1566       goto ON_EXIT;
1567     }
1568   }
1569 
1570   //
1571   // Uninstall the ComponentName and ComponentName2 protocol from iSCSI6 driver binding handle
1572   // if it has been installed.
1573   //
1574   Status = gBS->HandleProtocol (
1575                   gIScsiIp6DriverBinding.DriverBindingHandle,
1576                   &gEfiComponentNameProtocolGuid,
1577                   (VOID **) &ComponentName
1578                   );
1579   if (!EFI_ERROR (Status)) {
1580     Status = gBS->UninstallMultipleProtocolInterfaces (
1581            gIScsiIp6DriverBinding.DriverBindingHandle,
1582            &gEfiComponentNameProtocolGuid,
1583            ComponentName,
1584            NULL
1585            );
1586     if (EFI_ERROR (Status)) {
1587       goto ON_EXIT;
1588     }
1589   }
1590 
1591   Status = gBS->HandleProtocol (
1592                   gIScsiIp6DriverBinding.DriverBindingHandle,
1593                   &gEfiComponentName2ProtocolGuid,
1594                   (VOID **) &ComponentName2
1595                   );
1596   if (!EFI_ERROR (Status)) {
1597     gBS->UninstallMultipleProtocolInterfaces (
1598            gIScsiIp6DriverBinding.DriverBindingHandle,
1599            &gEfiComponentName2ProtocolGuid,
1600            ComponentName2,
1601            NULL
1602            );
1603     if (EFI_ERROR (Status)) {
1604       goto ON_EXIT;
1605     }
1606   }
1607 
1608   //
1609   // Uninstall the IScsiInitiatorNameProtocol and all the driver binding protocols.
1610   //
1611   Status = gBS->UninstallMultipleProtocolInterfaces (
1612                   gIScsiIp4DriverBinding.DriverBindingHandle,
1613                   &gEfiDriverBindingProtocolGuid,
1614                   &gIScsiIp4DriverBinding,
1615                   &gEfiIScsiInitiatorNameProtocolGuid,
1616                   &gIScsiInitiatorName,
1617                   NULL
1618                   );
1619   if (EFI_ERROR (Status)) {
1620     goto ON_EXIT;
1621   }
1622 
1623   Status = gBS->UninstallMultipleProtocolInterfaces (
1624                   gIScsiIp6DriverBinding.DriverBindingHandle,
1625                   &gEfiDriverBindingProtocolGuid,
1626                   &gIScsiIp6DriverBinding,
1627                   NULL
1628                   );
1629 
1630 ON_EXIT:
1631 
1632   if (DeviceHandleBuffer != NULL) {
1633     FreePool (DeviceHandleBuffer);
1634   }
1635 
1636   return Status;
1637 }
1638 
1639 /**
1640   This is the declaration of an EFI image entry point. This entry point is
1641   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1642   both device drivers and bus drivers.
1643 
1644   The entry point for iSCSI driver which initializes the global variables and
1645   installs the driver binding, component name protocol, iSCSI initiator name
1646   protocol and Authentication Info protocol on its image.
1647 
1648   @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
1649   @param[in]  SystemTable       A pointer to the EFI System Table.
1650 
1651   @retval EFI_SUCCESS           The operation completed successfully.
1652   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
1653 
1654 **/
1655 EFI_STATUS
1656 EFIAPI
IScsiDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1657 IScsiDriverEntryPoint (
1658   IN EFI_HANDLE         ImageHandle,
1659   IN EFI_SYSTEM_TABLE   *SystemTable
1660   )
1661 {
1662   EFI_STATUS                         Status;
1663   EFI_ISCSI_INITIATOR_NAME_PROTOCOL  *IScsiInitiatorName;
1664   EFI_AUTHENTICATION_INFO_PROTOCOL   *AuthenticationInfo;
1665 
1666   //
1667   // There should be only one EFI_ISCSI_INITIATOR_NAME_PROTOCOL.
1668   //
1669   Status = gBS->LocateProtocol (
1670                   &gEfiIScsiInitiatorNameProtocolGuid,
1671                   NULL,
1672                   (VOID **) &IScsiInitiatorName
1673                   );
1674   if (!EFI_ERROR (Status)) {
1675     return EFI_ACCESS_DENIED;
1676   }
1677 
1678   //
1679   // Initialize the EFI Driver Library.
1680   //
1681   Status = EfiLibInstallDriverBindingComponentName2 (
1682              ImageHandle,
1683              SystemTable,
1684              &gIScsiIp4DriverBinding,
1685              ImageHandle,
1686              &gIScsiComponentName,
1687              &gIScsiComponentName2
1688              );
1689   if (EFI_ERROR (Status)) {
1690     return Status;
1691   }
1692 
1693   Status = EfiLibInstallDriverBindingComponentName2 (
1694              ImageHandle,
1695              SystemTable,
1696              &gIScsiIp6DriverBinding,
1697              NULL,
1698              &gIScsiComponentName,
1699              &gIScsiComponentName2
1700              );
1701   if (EFI_ERROR (Status)) {
1702     goto Error1;
1703   }
1704 
1705   //
1706   // Install the iSCSI Initiator Name Protocol.
1707   //
1708   Status = gBS->InstallProtocolInterface (
1709                   &ImageHandle,
1710                   &gEfiIScsiInitiatorNameProtocolGuid,
1711                   EFI_NATIVE_INTERFACE,
1712                   &gIScsiInitiatorName
1713                   );
1714   if (EFI_ERROR (Status)) {
1715     goto Error2;
1716   }
1717 
1718   //
1719   // Create the private data structures.
1720   //
1721   mPrivate = AllocateZeroPool (sizeof (ISCSI_PRIVATE_DATA));
1722   if (mPrivate == NULL) {
1723     Status = EFI_OUT_OF_RESOURCES;
1724     goto Error3;
1725   }
1726 
1727   InitializeListHead (&mPrivate->NicInfoList);
1728   InitializeListHead (&mPrivate->AttemptConfigs);
1729 
1730   //
1731   // Initialize the configuration form of iSCSI.
1732   //
1733   Status = IScsiConfigFormInit (gIScsiIp4DriverBinding.DriverBindingHandle);
1734   if (EFI_ERROR (Status)) {
1735     goto Error4;
1736   }
1737 
1738   //
1739   // There should be only one EFI_AUTHENTICATION_INFO_PROTOCOL. If already exists,
1740   // do not produce the protocol instance.
1741   //
1742   Status = gBS->LocateProtocol (
1743                   &gEfiAuthenticationInfoProtocolGuid,
1744                   NULL,
1745                   (VOID **) &AuthenticationInfo
1746                   );
1747   if (Status == EFI_NOT_FOUND) {
1748     Status = gBS->InstallProtocolInterface (
1749                     &ImageHandle,
1750                     &gEfiAuthenticationInfoProtocolGuid,
1751                     EFI_NATIVE_INTERFACE,
1752                     &gIScsiAuthenticationInfo
1753                     );
1754     if (EFI_ERROR (Status)) {
1755       goto Error5;
1756     }
1757   }
1758 
1759   return EFI_SUCCESS;
1760 
1761 Error5:
1762   IScsiConfigFormUnload (gIScsiIp4DriverBinding.DriverBindingHandle);
1763 
1764 Error4:
1765   FreePool (mPrivate);
1766 
1767 Error3:
1768   gBS->UninstallMultipleProtocolInterfaces (
1769          ImageHandle,
1770          &gEfiIScsiInitiatorNameProtocolGuid,
1771          &gIScsiInitiatorName,
1772          NULL
1773          );
1774 
1775 Error2:
1776   gBS->UninstallMultipleProtocolInterfaces (
1777          gIScsiIp6DriverBinding.DriverBindingHandle,
1778          &gEfiDriverBindingProtocolGuid,
1779          &gIScsiIp6DriverBinding,
1780          &gEfiComponentName2ProtocolGuid,
1781          &gIScsiComponentName2,
1782          &gEfiComponentNameProtocolGuid,
1783          &gIScsiComponentName,
1784          NULL
1785          );
1786 
1787 Error1:
1788   gBS->UninstallMultipleProtocolInterfaces (
1789          ImageHandle,
1790          &gEfiDriverBindingProtocolGuid,
1791          &gIScsiIp4DriverBinding,
1792          &gEfiComponentName2ProtocolGuid,
1793          &gIScsiComponentName2,
1794          &gEfiComponentNameProtocolGuid,
1795          &gIScsiComponentName,
1796          NULL
1797          );
1798 
1799   return Status;
1800 }
1801 
1802