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