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