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