]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/IScsiDxe/IScsiMisc.c
MdeModulePkg\Bus\Ata\AtaAtapiPassThru: don't set PxSACT bit when issuing command
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
CommitLineData
4c5a5e0c 1/** @file\r
2 Miscellaneous routines for iSCSI driver.\r
3\r
18b24f92 4Copyright (c) 2004 - 2014, 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
17GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 IScsiHexString[] = "0123456789ABCDEFabcdef";\r
18\r
19/**\r
20 Removes (trims) specified leading and trailing characters from a string.\r
21\r
22 @param[in, out] Str Pointer to the null-terminated string to be trimmed.\r
23 On return, Str will hold the trimmed string. \r
24\r
25 @param[in] CharC Character will be trimmed from str.\r
26\r
27**/\r
28VOID\r
29IScsiStrTrim (\r
30 IN OUT CHAR16 *Str,\r
31 IN CHAR16 CharC\r
32 )\r
33{\r
34 CHAR16 *Pointer1;\r
35 CHAR16 *Pointer2;\r
36 \r
37 if (*Str == 0) {\r
38 return ;\r
39 }\r
40 \r
41 //\r
42 // Trim off the leading and trailing characters c\r
43 //\r
44 for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {\r
45 ;\r
46 }\r
47 \r
48 Pointer2 = Str;\r
49 if (Pointer2 == Pointer1) {\r
50 while (*Pointer1 != 0) {\r
51 Pointer2++;\r
52 Pointer1++;\r
53 }\r
54 } else {\r
55 while (*Pointer1 != 0) { \r
56 *Pointer2 = *Pointer1; \r
57 Pointer1++;\r
58 Pointer2++;\r
59 }\r
60 *Pointer2 = 0;\r
61 }\r
62 \r
63 \r
64 for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {\r
65 ;\r
66 }\r
67 if (Pointer1 != Str + StrLen(Str) - 1) { \r
68 *(Pointer1 + 1) = 0;\r
69 }\r
70}\r
71\r
72/**\r
73 Calculate the prefix length of the IPv4 subnet mask.\r
74\r
75 @param[in] SubnetMask The IPv4 subnet mask.\r
76\r
77 @return The prefix length of the subnet mask.\r
78 @retval 0 Other errors as indicated.\r
79\r
80**/\r
81UINT8\r
82IScsiGetSubnetMaskPrefixLength (\r
83 IN EFI_IPv4_ADDRESS *SubnetMask\r
84 )\r
85{\r
86 UINT8 Len;\r
87 UINT32 ReverseMask;\r
88\r
89 //\r
90 // The SubnetMask is in network byte order.\r
91 //\r
92 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);\r
93\r
94 //\r
95 // Reverse it.\r
96 //\r
97 ReverseMask = ~ReverseMask;\r
98\r
99 if ((ReverseMask & (ReverseMask + 1)) != 0) {\r
100 return 0;\r
101 }\r
102\r
103 Len = 0;\r
104\r
105 while (ReverseMask != 0) {\r
106 ReverseMask = ReverseMask >> 1;\r
107 Len++;\r
108 }\r
109\r
110 return (UINT8) (32 - Len);\r
111}\r
112\r
113\r
114/**\r
115 Convert the hexadecimal encoded LUN string into the 64-bit LUN.\r
116\r
117 @param[in] Str The hexadecimal encoded LUN string.\r
118 @param[out] Lun Storage to return the 64-bit LUN.\r
119\r
120 @retval EFI_SUCCESS The 64-bit LUN is stored in Lun.\r
121 @retval EFI_INVALID_PARAMETER The string is malformatted.\r
122\r
123**/\r
124EFI_STATUS\r
125IScsiAsciiStrToLun (\r
126 IN CHAR8 *Str,\r
127 OUT UINT8 *Lun\r
128 )\r
129{\r
130 UINTN Index, IndexValue, IndexNum, SizeStr;\r
131 CHAR8 TemStr[2];\r
132 UINT8 TemValue;\r
133 UINT16 Value[4];\r
134 \r
135 ZeroMem (Lun, 8);\r
136 ZeroMem (TemStr, 2);\r
137 ZeroMem ((UINT8 *) Value, sizeof (Value));\r
138 SizeStr = AsciiStrLen (Str); \r
139 IndexValue = 0;\r
140 IndexNum = 0;\r
141\r
142 for (Index = 0; Index < SizeStr; Index ++) {\r
143 TemStr[0] = Str[Index];\r
144 TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);\r
145 if (TemValue == 0 && TemStr[0] != '0') {\r
146 if ((TemStr[0] != '-') || (IndexNum == 0)) {\r
147 //\r
148 // Invalid Lun Char.\r
149 //\r
150 return EFI_INVALID_PARAMETER;\r
151 }\r
152 }\r
153 \r
154 if ((TemValue == 0) && (TemStr[0] == '-')) {\r
155 //\r
156 // Next Lun value.\r
157 //\r
158 if (++IndexValue >= 4) {\r
159 //\r
160 // Max 4 Lun value.\r
161 //\r
162 return EFI_INVALID_PARAMETER;\r
163 }\r
164 //\r
165 // Restart str index for the next lun value.\r
166 //\r
167 IndexNum = 0;\r
168 continue;\r
169 }\r
170 \r
171 if (++IndexNum > 4) {\r
172 // \r
173 // Each Lun Str can't exceed size 4, because it will be as UINT16 value.\r
174 //\r
175 return EFI_INVALID_PARAMETER;\r
176 }\r
177 \r
178 //\r
179 // Combine UINT16 value.\r
180 //\r
181 Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);\r
182 }\r
183 \r
184 for (Index = 0; Index <= IndexValue; Index ++) {\r
185 *((UINT16 *) &Lun[Index * 2]) = HTONS (Value[Index]);\r
186 }\r
187 \r
188 return EFI_SUCCESS;\r
189}\r
190\r
191/**\r
192 Convert the 64-bit LUN into the hexadecimal encoded LUN string.\r
193\r
194 @param[in] Lun The 64-bit LUN.\r
195 @param[out] Str The storage to return the hexadecimal encoded LUN string.\r
196\r
197**/\r
198VOID\r
199IScsiLunToUnicodeStr (\r
200 IN UINT8 *Lun,\r
201 OUT CHAR16 *Str\r
202 )\r
203{\r
204 UINTN Index;\r
205 CHAR16 *TempStr;\r
206\r
207 TempStr = Str;\r
208\r
209 for (Index = 0; Index < 4; Index++) {\r
210\r
211 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {\r
a4faf336 212 CopyMem (TempStr, L"0-", sizeof (L"0-"));\r
4c5a5e0c 213 } else {\r
214 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];\r
215 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];\r
216 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];\r
217 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];\r
218 TempStr[4] = L'-';\r
219 TempStr[5] = 0;\r
220\r
221 IScsiStrTrim (TempStr, L'0');\r
222 }\r
223\r
224 TempStr += StrLen (TempStr);\r
225 }\r
a4faf336
FS
226 //\r
227 // Remove the last '-'\r
228 //\r
4c5a5e0c 229 Str[StrLen (Str) - 1] = 0;\r
230\r
231 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {\r
232 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {\r
233 Str[Index - 1] = 0;\r
234 } else {\r
235 break;\r
236 }\r
237 }\r
238}\r
239\r
240/**\r
241 Convert the formatted IP address into the binary IP address.\r
242\r
243 @param[in] Str The UNICODE string.\r
244 @param[in] IpMode Indicates whether the IP address is v4 or v6.\r
245 @param[out] Ip The storage to return the ASCII string.\r
246\r
247 @retval EFI_SUCCESS The binary IP address is returned in Ip.\r
248 @retval EFI_INVALID_PARAMETER The IP string is malformatted or IpMode is\r
249 invalid.\r
250\r
251**/\r
252EFI_STATUS\r
253IScsiAsciiStrToIp (\r
254 IN CHAR8 *Str,\r
255 IN UINT8 IpMode,\r
256 OUT EFI_IP_ADDRESS *Ip\r
257 )\r
258{\r
259 EFI_STATUS Status;\r
260\r
261 if (IpMode == IP_MODE_IP4 || IpMode == IP_MODE_AUTOCONFIG_IP4) {\r
262 return NetLibAsciiStrToIp4 (Str, &Ip->v4);\r
263\r
264 } else if (IpMode == IP_MODE_IP6 || IpMode == IP_MODE_AUTOCONFIG_IP6) {\r
265 return NetLibAsciiStrToIp6 (Str, &Ip->v6);\r
266\r
267 } else if (IpMode == IP_MODE_AUTOCONFIG) {\r
268 Status = NetLibAsciiStrToIp4 (Str, &Ip->v4);\r
269 if (!EFI_ERROR (Status)) {\r
270 return Status;\r
271 }\r
272 return NetLibAsciiStrToIp6 (Str, &Ip->v6);\r
273\r
274 }\r
275\r
276 return EFI_INVALID_PARAMETER;\r
277}\r
278\r
279/**\r
280 Convert the mac address into a hexadecimal encoded "-" seperated string.\r
281\r
282 @param[in] Mac The mac address.\r
283 @param[in] Len Length in bytes of the mac address.\r
284 @param[in] VlanId VLAN ID of the network device.\r
285 @param[out] Str The storage to return the mac string.\r
286\r
287**/\r
288VOID\r
289IScsiMacAddrToStr (\r
290 IN EFI_MAC_ADDRESS *Mac,\r
291 IN UINT32 Len,\r
292 IN UINT16 VlanId,\r
293 OUT CHAR16 *Str\r
294 )\r
295{\r
296 UINT32 Index;\r
297 CHAR16 *String;\r
298\r
299 for (Index = 0; Index < Len; Index++) {\r
300 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];\r
301 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];\r
c0d494b5 302 Str[3 * Index + 2] = L':';\r
4c5a5e0c 303 }\r
304\r
305 String = &Str[3 * Index - 1] ;\r
306 if (VlanId != 0) {\r
307 String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);\r
308 }\r
309\r
310 *String = L'\0';\r
311}\r
312\r
313/**\r
314 Convert the binary encoded buffer into a hexadecimal encoded string.\r
315\r
316 @param[in] BinBuffer The buffer containing the binary data.\r
317 @param[in] BinLength Length of the binary buffer.\r
318 @param[in, out] HexStr Pointer to the string.\r
319 @param[in, out] HexLength The length of the string.\r
320\r
321 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string \r
322 and the length of the string is updated.\r
323 @retval EFI_BUFFER_TOO_SMALL The string is too small.\r
324 @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
325\r
326**/\r
327EFI_STATUS\r
328IScsiBinToHex (\r
329 IN UINT8 *BinBuffer,\r
330 IN UINT32 BinLength,\r
331 IN OUT CHAR8 *HexStr,\r
332 IN OUT UINT32 *HexLength\r
333 )\r
334{\r
335 UINTN Index;\r
336\r
337 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {\r
338 return EFI_INVALID_PARAMETER;\r
339 }\r
340\r
341 if (((*HexLength) - 3) < BinLength * 2) {\r
342 *HexLength = BinLength * 2 + 3;\r
343 return EFI_BUFFER_TOO_SMALL;\r
344 }\r
345\r
346 *HexLength = BinLength * 2 + 3;\r
347 //\r
348 // Prefix for Hex String.\r
349 //\r
350 HexStr[0] = '0';\r
351 HexStr[1] = 'x';\r
352\r
353 for (Index = 0; Index < BinLength; Index++) {\r
354 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];\r
355 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];\r
356 }\r
357\r
358 HexStr[Index * 2 + 2] = '\0';\r
359\r
360 return EFI_SUCCESS;\r
361}\r
362\r
363\r
364/**\r
365 Convert the hexadecimal string into a binary encoded buffer.\r
366\r
367 @param[in, out] BinBuffer The binary buffer.\r
368 @param[in, out] BinLength Length of the binary buffer.\r
369 @param[in] HexStr The hexadecimal string.\r
370\r
371 @retval EFI_SUCCESS The hexadecimal string is converted into a binary\r
372 encoded buffer.\r
373 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.\r
374\r
375**/\r
376EFI_STATUS\r
377IScsiHexToBin (\r
378 IN OUT UINT8 *BinBuffer,\r
379 IN OUT UINT32 *BinLength,\r
380 IN CHAR8 *HexStr\r
381 )\r
382{\r
383 UINTN Index;\r
384 UINTN Length;\r
385 UINT8 Digit;\r
386 CHAR8 TemStr[2];\r
387 \r
388 ZeroMem (TemStr, sizeof (TemStr));\r
389\r
390 //\r
391 // Find out how many hex characters the string has.\r
392 //\r
393 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {\r
394 HexStr += 2;\r
395 }\r
396 \r
397 Length = AsciiStrLen (HexStr);\r
398\r
399 for (Index = 0; Index < Length; Index ++) {\r
400 TemStr[0] = HexStr[Index];\r
401 Digit = (UINT8) AsciiStrHexToUint64 (TemStr);\r
402 if (Digit == 0 && TemStr[0] != '0') {\r
403 //\r
404 // Invalid Lun Char.\r
405 //\r
406 break;\r
407 }\r
408 if ((Index & 1) == 0) {\r
409 BinBuffer [Index/2] = Digit;\r
410 } else {\r
411 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);\r
412 }\r
413 }\r
414 \r
415 *BinLength = (UINT32) ((Index + 1)/2);\r
416\r
417 return EFI_SUCCESS;\r
418}\r
419\r
420\r
421/**\r
422 Convert the decimal-constant string or hex-constant string into a numerical value.\r
423\r
424 @param[in] Str String in decimal or hex.\r
425\r
426 @return The numerical value.\r
427\r
428**/\r
429UINTN\r
430IScsiNetNtoi (\r
431 IN CHAR8 *Str\r
432 )\r
433{\r
434 if ((Str[0] == '0') && ((Str[1] == 'x') || (Str[1] == 'X'))) {\r
435 Str += 2;\r
436\r
437 return AsciiStrHexToUintn (Str);\r
438 }\r
439\r
440 return AsciiStrDecimalToUintn (Str);\r
441}\r
442\r
443\r
444/**\r
445 Generate random numbers.\r
446\r
447 @param[in, out] Rand The buffer to contain random numbers.\r
448 @param[in] RandLength The length of the Rand buffer.\r
449\r
450**/\r
451VOID\r
452IScsiGenRandom (\r
453 IN OUT UINT8 *Rand,\r
454 IN UINTN RandLength\r
455 )\r
456{\r
457 UINT32 Random;\r
458\r
459 while (RandLength > 0) {\r
460 Random = NET_RANDOM (NetRandomInitSeed ());\r
461 *Rand++ = (UINT8) (Random);\r
462 RandLength--;\r
463 }\r
464}\r
465\r
466\r
467/**\r
468 Record the NIC info in global structure.\r
469\r
470 @param[in] Controller The handle of the controller.\r
471\r
472 @retval EFI_SUCCESS The operation is completed.\r
473 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resources to finish this\r
474 operation.\r
475\r
476**/\r
477EFI_STATUS\r
478IScsiAddNic (\r
479 IN EFI_HANDLE Controller\r
480 )\r
481{\r
482 EFI_STATUS Status;\r
483 ISCSI_NIC_INFO *NicInfo;\r
484 LIST_ENTRY *Entry;\r
485 EFI_MAC_ADDRESS MacAddr;\r
486 UINTN HwAddressSize;\r
487 UINT16 VlanId;\r
488\r
489 //\r
490 // Get MAC address of this network device.\r
491 //\r
492 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
493 if (EFI_ERROR (Status)) {\r
494 return Status;\r
495 }\r
496\r
497 //\r
498 // Get VLAN ID of this network device.\r
499 //\r
500 VlanId = NetLibGetVlanId (Controller);\r
501\r
502 //\r
503 // Check whether the NIC info already exists. Return directly if so.\r
504 //\r
505 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
506 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
507 if (NicInfo->HwAddressSize == HwAddressSize &&\r
508 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
509 NicInfo->VlanId == VlanId) {\r
510 mPrivate->CurrentNic = NicInfo->NicIndex;\r
511 return EFI_SUCCESS;\r
512 }\r
513\r
514 if (mPrivate->MaxNic < NicInfo->NicIndex) {\r
515 mPrivate->MaxNic = NicInfo->NicIndex;\r
516 }\r
517 }\r
518\r
519 //\r
520 // Record the NIC info in private structure.\r
521 //\r
522 NicInfo = AllocateZeroPool (sizeof (ISCSI_NIC_INFO));\r
523 if (NicInfo == NULL) {\r
524 return EFI_OUT_OF_RESOURCES;\r
525 }\r
526\r
527 CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);\r
528 NicInfo->HwAddressSize = (UINT32) HwAddressSize;\r
529 NicInfo->VlanId = VlanId;\r
530 NicInfo->NicIndex = (UINT8) (mPrivate->MaxNic + 1);\r
531 mPrivate->MaxNic = NicInfo->NicIndex;\r
532\r
533 //\r
534 // Get the PCI location.\r
535 //\r
536 IScsiGetNICPciLocation (\r
537 Controller,\r
538 &NicInfo->BusNumber,\r
539 &NicInfo->DeviceNumber,\r
540 &NicInfo->FunctionNumber\r
541 );\r
542\r
543 InsertTailList (&mPrivate->NicInfoList, &NicInfo->Link);\r
544 mPrivate->NicCount++;\r
545\r
546 mPrivate->CurrentNic = NicInfo->NicIndex;\r
547 return EFI_SUCCESS;\r
548}\r
549\r
550\r
551/**\r
552 Delete the recorded NIC info from global structure. Also delete corresponding\r
553 attempts.\r
554\r
555 @param[in] Controller The handle of the controller.\r
556\r
557 @retval EFI_SUCCESS The operation is completed.\r
558 @retval EFI_NOT_FOUND The NIC info to be deleted is not recorded.\r
559\r
560**/\r
561EFI_STATUS\r
562IScsiRemoveNic (\r
563 IN EFI_HANDLE Controller\r
564 )\r
565{\r
566 EFI_STATUS Status;\r
567 ISCSI_NIC_INFO *NicInfo;\r
568 LIST_ENTRY *Entry;\r
569 LIST_ENTRY *NextEntry;\r
570 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
571 ISCSI_NIC_INFO *ThisNic;\r
572 EFI_MAC_ADDRESS MacAddr;\r
573 UINTN HwAddressSize;\r
574 UINT16 VlanId;\r
575\r
576 //\r
577 // Get MAC address of this network device.\r
578 //\r
579 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
580 if (EFI_ERROR (Status)) {\r
581 return Status;\r
582 }\r
583\r
584 //\r
585 // Get VLAN ID of this network device.\r
586 //\r
587 VlanId = NetLibGetVlanId (Controller);\r
588\r
589 //\r
590 // Check whether the NIC information exists.\r
591 //\r
592 ThisNic = NULL;\r
593\r
594 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
595 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
596 if (NicInfo->HwAddressSize == HwAddressSize &&\r
597 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&\r
598 NicInfo->VlanId == VlanId) {\r
599\r
600 ThisNic = NicInfo;\r
601 break;\r
602 }\r
603 }\r
604\r
605 if (ThisNic == NULL) {\r
606 return EFI_NOT_FOUND;\r
607 }\r
608\r
609 mPrivate->CurrentNic = ThisNic->NicIndex;\r
610\r
611 RemoveEntryList (&ThisNic->Link);\r
612 FreePool (ThisNic);\r
613 mPrivate->NicCount--;\r
614\r
615 //\r
616 // Remove all attempts related to this NIC.\r
617 //\r
618 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {\r
619 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);\r
620 if (AttemptConfigData->NicIndex == mPrivate->CurrentNic) {\r
621 RemoveEntryList (&AttemptConfigData->Link);\r
622 mPrivate->AttemptCount--;\r
623\r
624 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {\r
625 if (--mPrivate->MpioCount == 0) {\r
626 mPrivate->EnableMpio = FALSE;\r
627 }\r
628\r
629 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {\r
630 mPrivate->Krb5MpioCount--;\r
631 }\r
632\r
633 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {\r
634 mPrivate->SinglePathCount--;\r
635\r
636 if (mPrivate->ValidSinglePathCount > 0) {\r
637 mPrivate->ValidSinglePathCount--;\r
638 }\r
639 }\r
640\r
641 FreePool (AttemptConfigData);\r
642 }\r
643 }\r
644\r
c0d494b5 645 //\r
646 // Free attempt is created but not saved to system.\r
647 //\r
648 if (mPrivate->NewAttempt != NULL) {\r
649 FreePool (mPrivate->NewAttempt);\r
650 mPrivate->NewAttempt = NULL;\r
651 }\r
652\r
4c5a5e0c 653 return EFI_SUCCESS;\r
654}\r
655\r
656\r
657/**\r
658 Get the recorded NIC info from global structure by the Index.\r
659\r
660 @param[in] NicIndex The index indicates the position of NIC info.\r
661\r
662 @return Pointer to the NIC info, or NULL if not found.\r
663\r
664**/\r
665ISCSI_NIC_INFO *\r
666IScsiGetNicInfoByIndex (\r
667 IN UINT8 NicIndex\r
668 )\r
669{\r
670 LIST_ENTRY *Entry;\r
671 ISCSI_NIC_INFO *NicInfo;\r
672\r
673 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {\r
674 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);\r
675 if (NicInfo->NicIndex == NicIndex) {\r
676 return NicInfo;\r
677 }\r
678 }\r
679\r
680 return NULL;\r
681}\r
682\r
683\r
684/**\r
685 Get the NIC's PCI location and return it accroding to the composited\r
686 format defined in iSCSI Boot Firmware Table.\r
687\r
688 @param[in] Controller The handle of the controller.\r
689 @param[out] Bus The bus number.\r
690 @param[out] Device The device number.\r
691 @param[out] Function The function number.\r
692\r
693 @return The composited representation of the NIC PCI location.\r
694\r
695**/\r
696UINT16\r
697IScsiGetNICPciLocation (\r
698 IN EFI_HANDLE Controller,\r
699 OUT UINTN *Bus,\r
700 OUT UINTN *Device,\r
701 OUT UINTN *Function\r
702 )\r
703{\r
704 EFI_STATUS Status;\r
705 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
706 EFI_HANDLE PciIoHandle;\r
707 EFI_PCI_IO_PROTOCOL *PciIo;\r
708 UINTN Segment;\r
709\r
710 Status = gBS->HandleProtocol (\r
711 Controller,\r
712 &gEfiDevicePathProtocolGuid,\r
713 (VOID **) &DevicePath\r
714 );\r
715 if (EFI_ERROR (Status)) {\r
716 return 0;\r
717 }\r
718\r
719 Status = gBS->LocateDevicePath (\r
720 &gEfiPciIoProtocolGuid,\r
721 &DevicePath,\r
722 &PciIoHandle\r
723 );\r
724 if (EFI_ERROR (Status)) {\r
725 return 0;\r
726 }\r
727\r
728 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);\r
729 if (EFI_ERROR (Status)) {\r
730 return 0;\r
731 }\r
732\r
733 Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);\r
734 if (EFI_ERROR (Status)) {\r
735 return 0;\r
736 }\r
737\r
738 return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);\r
739}\r
740\r
741\r
742/**\r
743 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
744 buffer, and the size of the buffer. If failure, return NULL.\r
745\r
746 @param[in] Name String part of EFI variable name.\r
747 @param[in] VendorGuid GUID part of EFI variable name.\r
748 @param[out] VariableSize Returns the size of the EFI variable that was read.\r
749\r
750 @return Dynamically allocated memory that contains a copy of the EFI variable.\r
751 @return Caller is responsible freeing the buffer.\r
752 @retval NULL Variable was not read.\r
753\r
754**/\r
755VOID *\r
756IScsiGetVariableAndSize (\r
757 IN CHAR16 *Name,\r
758 IN EFI_GUID *VendorGuid,\r
759 OUT UINTN *VariableSize\r
760 )\r
761{\r
762 EFI_STATUS Status;\r
763 UINTN BufferSize;\r
764 VOID *Buffer;\r
765\r
766 Buffer = NULL;\r
767\r
768 //\r
769 // Pass in a zero size buffer to find the required buffer size.\r
770 //\r
771 BufferSize = 0;\r
772 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
773 if (Status == EFI_BUFFER_TOO_SMALL) {\r
774 //\r
775 // Allocate the buffer to return\r
776 //\r
777 Buffer = AllocateZeroPool (BufferSize);\r
778 if (Buffer == NULL) {\r
779 return NULL;\r
780 }\r
781 //\r
782 // Read variable into the allocated buffer.\r
783 //\r
784 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
785 if (EFI_ERROR (Status)) {\r
786 BufferSize = 0;\r
787 }\r
788 }\r
789\r
790 *VariableSize = BufferSize;\r
791 return Buffer;\r
792}\r
793\r
794\r
795/**\r
796 Create the iSCSI driver data.\r
797\r
798 @param[in] Image The handle of the driver image.\r
799 @param[in] Controller The handle of the controller.\r
800\r
801 @return The iSCSI driver data created.\r
802 @retval NULL Other errors as indicated.\r
803\r
804**/\r
805ISCSI_DRIVER_DATA *\r
806IScsiCreateDriverData (\r
807 IN EFI_HANDLE Image,\r
808 IN EFI_HANDLE Controller\r
809 )\r
810{\r
811 ISCSI_DRIVER_DATA *Private;\r
812 EFI_STATUS Status;\r
813\r
814 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));\r
815 if (Private == NULL) {\r
816 return NULL;\r
817 }\r
818\r
819 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;\r
820 Private->Image = Image;\r
821 Private->Controller = Controller;\r
822 Private->Session = NULL;\r
823\r
824 //\r
825 // Create an event to be signaled when the BS to RT transition is triggerd so\r
826 // as to abort the iSCSI session.\r
827 //\r
828 Status = gBS->CreateEventEx (\r
829 EVT_NOTIFY_SIGNAL,\r
830 TPL_CALLBACK,\r
831 IScsiOnExitBootService,\r
832 Private,\r
833 &gEfiEventExitBootServicesGuid,\r
834 &Private->ExitBootServiceEvent\r
835 );\r
836 if (EFI_ERROR (Status)) {\r
837 FreePool (Private);\r
838 return NULL;\r
839 }\r
840\r
841 Private->ExtScsiPassThruHandle = NULL;\r
842 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));\r
843\r
844 //\r
845 // 0 is designated to the TargetId, so use another value for the AdapterId.\r
846 //\r
847 Private->ExtScsiPassThruMode.AdapterId = 2;\r
848 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;\r
849 Private->ExtScsiPassThruMode.IoAlign = 4;\r
850 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;\r
851\r
852 return Private;\r
853}\r
854\r
855\r
856/**\r
857 Clean the iSCSI driver data.\r
858\r
859 @param[in] Private The iSCSI driver data.\r
860\r
861**/\r
862VOID\r
863IScsiCleanDriverData (\r
864 IN ISCSI_DRIVER_DATA *Private\r
865 )\r
866{\r
867 EFI_STATUS Status;\r
868\r
869 if (Private->DevicePath != NULL) {\r
870 gBS->UninstallProtocolInterface (\r
871 Private->ExtScsiPassThruHandle,\r
872 &gEfiDevicePathProtocolGuid,\r
873 Private->DevicePath\r
874 );\r
875\r
876 FreePool (Private->DevicePath);\r
877 }\r
878\r
879 if (Private->ExtScsiPassThruHandle != NULL) {\r
880 Status = gBS->UninstallProtocolInterface (\r
881 Private->ExtScsiPassThruHandle,\r
882 &gEfiExtScsiPassThruProtocolGuid,\r
883 &Private->IScsiExtScsiPassThru\r
884 );\r
885 if (!EFI_ERROR (Status)) {\r
886 mPrivate->OneSessionEstablished = FALSE;\r
887 }\r
888 }\r
889\r
890 gBS->CloseEvent (Private->ExitBootServiceEvent);\r
891\r
892 FreePool (Private);\r
893}\r
894\r
b7cc5bf1
WJ
895/**\r
896 Check wheather the Controller handle is configured to use DHCP protocol.\r
897\r
898 @param[in] Controller The handle of the controller.\r
899 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
900 \r
901 @retval TRUE The handle of the controller need the Dhcp protocol.\r
902 @retval FALSE The handle of the controller does not need the Dhcp protocol.\r
903 \r
904**/\r
905BOOLEAN\r
906IScsiDhcpIsConfigured (\r
907 IN EFI_HANDLE Controller,\r
908 IN UINT8 IpVersion\r
909 )\r
910{\r
911 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
912 UINT8 *AttemptConfigOrder;\r
913 UINTN AttemptConfigOrderSize;\r
914 UINTN Index;\r
915 EFI_STATUS Status;\r
916 EFI_MAC_ADDRESS MacAddr;\r
917 UINTN HwAddressSize;\r
918 UINT16 VlanId;\r
919 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
920 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];\r
921 \r
922 AttemptConfigOrder = IScsiGetVariableAndSize (\r
923 L"AttemptOrder",\r
924 &gIScsiConfigGuid,\r
925 &AttemptConfigOrderSize\r
926 );\r
927 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
928 return FALSE;\r
929 }\r
930 \r
931 //\r
932 // Get MAC address of this network device.\r
933 //\r
934 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);\r
935 if(EFI_ERROR (Status)) {\r
936 return FALSE;\r
937 }\r
938 //\r
939 // Get VLAN ID of this network device.\r
940 //\r
941 VlanId = NetLibGetVlanId (Controller);\r
942 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);\r
943 \r
944 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
945 UnicodeSPrint (\r
946 AttemptName,\r
947 (UINTN) 128,\r
948 L"%s%d",\r
949 MacString,\r
950 (UINTN) AttemptConfigOrder[Index]\r
951 );\r
952 Status = GetVariable2 (\r
953 AttemptName,\r
954 &gEfiIScsiInitiatorNameProtocolGuid,\r
955 (VOID**)&AttemptTmp,\r
956 NULL\r
957 );\r
107e3d7a 958 if(AttemptTmp == NULL || EFI_ERROR (Status)) {\r
b7cc5bf1
WJ
959 continue;\r
960 }\r
107e3d7a 961 \r
b7cc5bf1
WJ
962 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);\r
963\r
964 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
965 FreePool (AttemptTmp);\r
966 continue;\r
967 }\r
968\r
969 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG && \r
970 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {\r
971 FreePool (AttemptTmp);\r
972 continue;\r
973 }\r
974 \r
975 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||\r
976 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||\r
977 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) { \r
978 FreePool (AttemptTmp);\r
979 FreePool (AttemptConfigOrder);\r
980 return TRUE;\r
981 }\r
982\r
983 FreePool (AttemptTmp);\r
984 }\r
985 \r
986 FreePool (AttemptConfigOrder);\r
987 return FALSE;\r
988}\r
4c5a5e0c 989\r
990/**\r
991 Get the various configuration data.\r
992\r
993 @param[in] Private The iSCSI driver data.\r
994\r
995 @retval EFI_SUCCESS The configuration data is retrieved.\r
996 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet.\r
997\r
998**/\r
999EFI_STATUS\r
1000IScsiGetConfigData (\r
1001 IN ISCSI_DRIVER_DATA *Private\r
1002 )\r
1003{\r
1004 EFI_STATUS Status;\r
1005 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];\r
1006 UINTN Index;\r
1007 ISCSI_NIC_INFO *NicInfo;\r
1008 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;\r
1009 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;\r
1010 UINT8 *AttemptConfigOrder;\r
1011 UINTN AttemptConfigOrderSize;\r
1012 CHAR16 IScsiMode[64];\r
1013 CHAR16 IpMode[64];\r
1014\r
1015 //\r
1016 // There should be at least one attempt configured.\r
1017 //\r
1018 AttemptConfigOrder = IScsiGetVariableAndSize (\r
1019 L"AttemptOrder",\r
9bdc6592 1020 &gIScsiConfigGuid,\r
4c5a5e0c 1021 &AttemptConfigOrderSize\r
1022 );\r
1023 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {\r
1024 return EFI_NOT_FOUND;\r
1025 }\r
1026\r
1027 //\r
1028 // Get the iSCSI Initiator Name.\r
1029 //\r
1030 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;\r
1031 Status = gIScsiInitiatorName.Get (\r
1032 &gIScsiInitiatorName,\r
1033 &mPrivate->InitiatorNameLength,\r
1034 mPrivate->InitiatorName\r
1035 );\r
1036 if (EFI_ERROR (Status)) {\r
1037 return Status;\r
1038 }\r
1039\r
1040 //\r
1041 // Get the normal configuration.\r
1042 //\r
1043 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1044\r
1045 //\r
1046 // Check whether the attempt exists in AttemptConfig.\r
1047 //\r
1048 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]); \r
1049 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
1050 continue;\r
1051 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {\r
1052 //\r
1053 // Check the autoconfig path to see whether it should be retried.\r
1054 //\r
1055 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&\r
1056 AttemptTmp->AutoConfigureMode != IP_MODE_AUTOCONFIG_SUCCESS) {\r
1057 if (mPrivate->Ipv6Flag &&\r
1058 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {\r
1059 //\r
1060 // Autoconfigure for IP6 already attempted but failed. Do not try again.\r
1061 //\r
1062 continue;\r
1063 } else if (!mPrivate->Ipv6Flag &&\r
1064 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {\r
1065 //\r
1066 // Autoconfigure for IP4 already attempted but failed. Do not try again.\r
1067 //\r
1068 continue;\r
1069 } else {\r
1070 //\r
1071 // Try another approach for this autoconfigure path.\r
1072 //\r
1073 AttemptTmp->AutoConfigureMode =\r
1074 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
1075 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;\r
1076 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE;\r
1077 AttemptTmp->DhcpSuccess = FALSE;\r
1078\r
1079 //\r
1080 // Get some information from the dhcp server.\r
1081 //\r
1082 if (!mPrivate->Ipv6Flag) {\r
1083 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);\r
1084 if (!EFI_ERROR (Status)) {\r
1085 AttemptTmp->DhcpSuccess = TRUE;\r
1086 }\r
1087 } else {\r
1088 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);\r
1089 if (!EFI_ERROR (Status)) {\r
1090 AttemptTmp->DhcpSuccess = TRUE;\r
1091 }\r
1092 }\r
1093\r
1094 //\r
1095 // Refresh the state of this attempt to NVR.\r
1096 //\r
1097 AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString);\r
1098 UnicodeSPrint (\r
1099 mPrivate->PortString,\r
1100 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1101 L"%s%d",\r
1102 MacString,\r
1103 (UINTN) AttemptTmp->AttemptConfigIndex\r
1104 );\r
1105\r
1106 gRT->SetVariable (\r
1107 mPrivate->PortString,\r
1108 &gEfiIScsiInitiatorNameProtocolGuid,\r
1109 ISCSI_CONFIG_VAR_ATTR,\r
1110 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1111 AttemptTmp\r
1112 );\r
1113\r
1114 continue;\r
1115 }\r
1116 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp && !AttemptTmp->ValidPath) {\r
1117 //\r
1118 // Get DHCP information for already added, but failed, attempt.\r
1119 //\r
1120 AttemptTmp->DhcpSuccess = FALSE;\r
1121 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {\r
1122 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);\r
1123 if (!EFI_ERROR (Status)) {\r
1124 AttemptTmp->DhcpSuccess = TRUE;\r
1125 }\r
1126 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {\r
1127 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);\r
1128 if (!EFI_ERROR (Status)) {\r
1129 AttemptTmp->DhcpSuccess = TRUE;\r
1130 }\r
1131 }\r
1132\r
1133 //\r
1134 // Refresh the state of this attempt to NVR.\r
1135 //\r
1136 AsciiStrToUnicodeStr (AttemptTmp->MacString, MacString);\r
1137 UnicodeSPrint (\r
1138 mPrivate->PortString,\r
1139 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1140 L"%s%d",\r
1141 MacString,\r
1142 (UINTN) AttemptTmp->AttemptConfigIndex\r
1143 );\r
1144\r
1145 gRT->SetVariable (\r
1146 mPrivate->PortString,\r
1147 &gEfiIScsiInitiatorNameProtocolGuid,\r
1148 ISCSI_CONFIG_VAR_ATTR,\r
1149 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1150 AttemptTmp\r
1151 );\r
1152\r
1153 continue;\r
1154\r
1155 } else {\r
1156 continue;\r
1157 }\r
1158 }\r
1159\r
1160 //\r
1161 // This attempt does not exist in AttemptConfig. Try to add a new one.\r
1162 //\r
1163\r
1164 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);\r
1165 ASSERT (NicInfo != NULL);\r
1166 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);\r
1167 UnicodeSPrint (\r
1168 mPrivate->PortString,\r
1169 (UINTN) 128,\r
1170 L"%s%d",\r
1171 MacString,\r
1172 (UINTN) AttemptConfigOrder[Index]\r
1173 );\r
1174\r
bf4a3dbd
ED
1175 GetVariable2 (\r
1176 mPrivate->PortString,\r
1177 &gEfiIScsiInitiatorNameProtocolGuid,\r
f01b91ae 1178 (VOID**)&AttemptConfigData,\r
bf4a3dbd
ED
1179 NULL\r
1180 );\r
4c5a5e0c 1181\r
1182 if (AttemptConfigData == NULL) {\r
1183 continue;\r
1184 }\r
1185\r
1186 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);\r
1187\r
1188 AttemptConfigData->NicIndex = NicInfo->NicIndex;\r
1189 AttemptConfigData->DhcpSuccess = FALSE;\r
1190 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);\r
1191 AttemptConfigData->ValidPath = FALSE;\r
1192\r
1193 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
1194 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;\r
1195 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE;\r
1196\r
1197 AttemptConfigData->AutoConfigureMode =\r
1198 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);\r
1199 }\r
1200 \r
1201 //\r
1202 // Get some information from dhcp server.\r
1203 //\r
1204 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&\r
1205 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {\r
1206\r
1207 if (!mPrivate->Ipv6Flag &&\r
1208 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||\r
1209 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {\r
1210 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);\r
1211 if (!EFI_ERROR (Status)) {\r
1212 AttemptConfigData->DhcpSuccess = TRUE;\r
1213 }\r
1214 } else if (mPrivate->Ipv6Flag &&\r
1215 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||\r
1216 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {\r
1217 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);\r
1218 if (!EFI_ERROR (Status)) {\r
1219 AttemptConfigData->DhcpSuccess = TRUE;\r
1220 }\r
1221 }\r
1222\r
1223 //\r
1224 // Refresh the state of this attempt to NVR.\r
1225 //\r
1226 AsciiStrToUnicodeStr (AttemptConfigData->MacString, MacString);\r
1227 UnicodeSPrint (\r
1228 mPrivate->PortString,\r
1229 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1230 L"%s%d",\r
1231 MacString,\r
1232 (UINTN) AttemptConfigData->AttemptConfigIndex\r
1233 );\r
1234\r
1235 gRT->SetVariable (\r
1236 mPrivate->PortString,\r
1237 &gEfiIScsiInitiatorNameProtocolGuid,\r
1238 ISCSI_CONFIG_VAR_ATTR,\r
1239 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),\r
1240 AttemptConfigData\r
1241 );\r
1242 }\r
1243\r
1244 //\r
1245 // Update Attempt Help Info.\r
1246 //\r
1247\r
1248 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {\r
1249 UnicodeSPrint (IScsiMode, 64, L"Disabled");\r
1250 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
1251 UnicodeSPrint (IScsiMode, 64, L"Enabled");\r
1252 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1253 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");\r
1254 }\r
1255\r
1256 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {\r
1257 UnicodeSPrint (IpMode, 64, L"IP4");\r
1258 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {\r
1259 UnicodeSPrint (IpMode, 64, L"IP6");\r
1260 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {\r
1261 UnicodeSPrint (IpMode, 64, L"Autoconfigure");\r
1262 }\r
1263\r
1264 UnicodeSPrint (\r
1265 mPrivate->PortString,\r
1266 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,\r
1267 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",\r
1268 MacString,\r
1269 NicInfo->BusNumber,\r
1270 NicInfo->DeviceNumber,\r
1271 NicInfo->FunctionNumber,\r
1272 IScsiMode,\r
1273 IpMode\r
1274 );\r
1275\r
1276 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (\r
1277 mCallbackInfo->RegisteredHandle,\r
1278 0,\r
1279 mPrivate->PortString,\r
1280 NULL\r
1281 );\r
1282 ASSERT (AttemptConfigData->AttemptTitleHelpToken != 0);\r
1283\r
1284 //\r
1285 // Record the attempt in global link list.\r
1286 //\r
1287 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
1288 mPrivate->AttemptCount++;\r
1289\r
1290 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {\r
1291 mPrivate->MpioCount++;\r
1292 mPrivate->EnableMpio = TRUE;\r
1293\r
1294 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {\r
1295 mPrivate->Krb5MpioCount++;\r
1296 }\r
1297 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {\r
1298 mPrivate->SinglePathCount++;\r
1299 }\r
1300 }\r
1301\r
1302 //\r
1303 // Reorder the AttemptConfig by the configured order.\r
1304 //\r
1305 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {\r
1306 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);\r
1307 if (AttemptConfigData == NULL) {\r
1308 continue;\r
1309 }\r
1310\r
1311 RemoveEntryList (&AttemptConfigData->Link);\r
1312 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);\r
1313 }\r
1314\r
1315 //\r
1316 // Update the Main Form.\r
1317 //\r
1318 IScsiConfigUpdateAttempt ();\r
1319\r
1320 FreePool (AttemptConfigOrder);\r
1321\r
1322 //\r
1323 // There should be at least one attempt configuration.\r
1324 //\r
1325 if (!mPrivate->EnableMpio) {\r
1326 if (mPrivate->SinglePathCount == 0) {\r
1327 return EFI_NOT_FOUND;\r
1328 }\r
1329 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;\r
1330 }\r
1331\r
1332 return EFI_SUCCESS;\r
1333}\r
1334\r
1335\r
1336/**\r
1337 Get the device path of the iSCSI tcp connection and update it.\r
1338\r
1339 @param Session The iSCSI session.\r
1340\r
1341 @return The updated device path.\r
1342 @retval NULL Other errors as indicated.\r
1343\r
1344**/\r
1345EFI_DEVICE_PATH_PROTOCOL *\r
1346IScsiGetTcpConnDevicePath (\r
1347 IN ISCSI_SESSION *Session\r
1348 )\r
1349{\r
1350 ISCSI_CONNECTION *Conn;\r
1351 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1352 EFI_STATUS Status;\r
1353 EFI_DEV_PATH *DPathNode;\r
1354\r
1355 if (Session->State != SESSION_STATE_LOGGED_IN) {\r
1356 return NULL;\r
1357 }\r
1358\r
1359 Conn = NET_LIST_USER_STRUCT_S (\r
1360 Session->Conns.ForwardLink,\r
1361 ISCSI_CONNECTION,\r
1362 Link,\r
1363 ISCSI_CONNECTION_SIGNATURE\r
1364 );\r
1365\r
1366 Status = gBS->HandleProtocol (\r
1367 Conn->TcpIo.Handle,\r
1368 &gEfiDevicePathProtocolGuid,\r
1369 (VOID **) &DevicePath\r
1370 ); \r
1371 if (EFI_ERROR (Status)) {\r
1372 return NULL;\r
1373 }\r
1374 //\r
1375 // Duplicate it.\r
1376 //\r
1377 DevicePath = DuplicateDevicePath (DevicePath);\r
1378 if (DevicePath == NULL) {\r
1379 return NULL;\r
1380 }\r
1381\r
1382 DPathNode = (EFI_DEV_PATH *) DevicePath;\r
1383\r
1384 while (!IsDevicePathEnd (&DPathNode->DevPath)) {\r
1385 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {\r
1386 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {\r
1387 DPathNode->Ipv4.LocalPort = 0;\r
501793fa
RN
1388\r
1389 DPathNode->Ipv4.StaticIpAddress = \r
1390 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);\r
1391\r
1392 IP4_COPY_ADDRESS (\r
1393 &DPathNode->Ipv4.GatewayIpAddress,\r
1394 &Session->ConfigData->SessionConfigData.Gateway\r
1395 );\r
1396\r
1397 IP4_COPY_ADDRESS (\r
1398 &DPathNode->Ipv4.SubnetMask,\r
1399 &Session->ConfigData->SessionConfigData.SubnetMask\r
1400 );\r
4c5a5e0c 1401 break;\r
1402 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {\r
1403 DPathNode->Ipv6.LocalPort = 0;\r
501793fa
RN
1404 DPathNode->Ipv6.IpAddressOrigin = 0;\r
1405 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;\r
1406 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));\r
4c5a5e0c 1407 break;\r
1408 }\r
1409 }\r
1410\r
1411 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);\r
1412 }\r
1413\r
1414 return DevicePath;\r
1415}\r
1416\r
1417\r
1418/**\r
1419 Abort the session when the transition from BS to RT is initiated.\r
1420\r
1421 @param[in] Event The event signaled.\r
1422 @param[in] Context The iSCSI driver data.\r
1423\r
1424**/\r
1425VOID\r
1426EFIAPI\r
1427IScsiOnExitBootService (\r
1428 IN EFI_EVENT Event,\r
1429 IN VOID *Context\r
1430 )\r
1431{\r
1432 ISCSI_DRIVER_DATA *Private;\r
1433\r
1434 Private = (ISCSI_DRIVER_DATA *) Context;\r
1435 gBS->CloseEvent (Private->ExitBootServiceEvent);\r
1436\r
1437 if (Private->Session != NULL) {\r
1438 IScsiSessionAbort (Private->Session);\r
1439 }\r
1440}\r
18b24f92
FS
1441\r
1442/**\r
1443 Tests whether a controller handle is being managed by IScsi driver.\r
1444\r
1445 This function tests whether the driver specified by DriverBindingHandle is\r
1446 currently managing the controller specified by ControllerHandle. This test\r
1447 is performed by evaluating if the the protocol specified by ProtocolGuid is\r
1448 present on ControllerHandle and is was opened by DriverBindingHandle and Nic\r
1449 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER. \r
1450 If ProtocolGuid is NULL, then ASSERT().\r
1451\r
1452 @param ControllerHandle A handle for a controller to test.\r
1453 @param DriverBindingHandle Specifies the driver binding handle for the\r
1454 driver.\r
1455 @param ProtocolGuid Specifies the protocol that the driver specified\r
1456 by DriverBindingHandle opens in its Start()\r
1457 function.\r
1458\r
1459 @retval EFI_SUCCESS ControllerHandle is managed by the driver\r
1460 specified by DriverBindingHandle.\r
1461 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver\r
1462 specified by DriverBindingHandle.\r
1463\r
1464**/\r
1465EFI_STATUS\r
1466EFIAPI\r
1467IScsiTestManagedDevice (\r
1468 IN EFI_HANDLE ControllerHandle,\r
1469 IN EFI_HANDLE DriverBindingHandle,\r
1470 IN EFI_GUID *ProtocolGuid\r
1471 )\r
1472{\r
1473 EFI_STATUS Status;\r
1474 VOID *ManagedInterface;\r
1475 EFI_HANDLE NicControllerHandle;\r
1476\r
1477 ASSERT (ProtocolGuid != NULL);\r
1478\r
1479 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);\r
1480 if (NicControllerHandle == NULL) {\r
1481 return EFI_UNSUPPORTED;\r
1482 }\r
1483\r
1484 Status = gBS->OpenProtocol (\r
1485 ControllerHandle,\r
1486 (EFI_GUID *) ProtocolGuid,\r
1487 &ManagedInterface,\r
1488 DriverBindingHandle,\r
1489 NicControllerHandle,\r
1490 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1491 );\r
1492 if (!EFI_ERROR (Status)) {\r
1493 gBS->CloseProtocol (\r
1494 ControllerHandle,\r
1495 (EFI_GUID *) ProtocolGuid,\r
1496 DriverBindingHandle,\r
1497 NicControllerHandle\r
1498 );\r
1499 return EFI_UNSUPPORTED;\r
1500 }\r
1501\r
1502 if (Status != EFI_ALREADY_STARTED) {\r
1503 return EFI_UNSUPPORTED;\r
1504 }\r
1505\r
1506 return EFI_SUCCESS;\r
1507}\r