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