]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/IScsiDxe/IScsiMisc.c
NetworkPkg: Fix potential bug if the iSCSI use dns protocol.
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiMisc.c
1 /** @file
2 Miscellaneous routines for iSCSI driver.
3
4 Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "IScsiImpl.h"
16
17 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 IScsiHexString[] = "0123456789ABCDEFabcdef";
18
19 /**
20 Removes (trims) specified leading and trailing characters from a string.
21
22 @param[in, out] Str Pointer to the null-terminated string to be trimmed.
23 On return, Str will hold the trimmed string.
24
25 @param[in] CharC Character will be trimmed from str.
26
27 **/
28 VOID
29 IScsiStrTrim (
30 IN OUT CHAR16 *Str,
31 IN CHAR16 CharC
32 )
33 {
34 CHAR16 *Pointer1;
35 CHAR16 *Pointer2;
36
37 if (*Str == 0) {
38 return ;
39 }
40
41 //
42 // Trim off the leading and trailing characters c
43 //
44 for (Pointer1 = Str; (*Pointer1 != 0) && (*Pointer1 == CharC); Pointer1++) {
45 ;
46 }
47
48 Pointer2 = Str;
49 if (Pointer2 == Pointer1) {
50 while (*Pointer1 != 0) {
51 Pointer2++;
52 Pointer1++;
53 }
54 } else {
55 while (*Pointer1 != 0) {
56 *Pointer2 = *Pointer1;
57 Pointer1++;
58 Pointer2++;
59 }
60 *Pointer2 = 0;
61 }
62
63
64 for (Pointer1 = Str + StrLen(Str) - 1; Pointer1 >= Str && *Pointer1 == CharC; Pointer1--) {
65 ;
66 }
67 if (Pointer1 != Str + StrLen(Str) - 1) {
68 *(Pointer1 + 1) = 0;
69 }
70 }
71
72 /**
73 Calculate the prefix length of the IPv4 subnet mask.
74
75 @param[in] SubnetMask The IPv4 subnet mask.
76
77 @return The prefix length of the subnet mask.
78 @retval 0 Other errors as indicated.
79
80 **/
81 UINT8
82 IScsiGetSubnetMaskPrefixLength (
83 IN EFI_IPv4_ADDRESS *SubnetMask
84 )
85 {
86 UINT8 Len;
87 UINT32 ReverseMask;
88
89 //
90 // The SubnetMask is in network byte order.
91 //
92 ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);
93
94 //
95 // Reverse it.
96 //
97 ReverseMask = ~ReverseMask;
98
99 if ((ReverseMask & (ReverseMask + 1)) != 0) {
100 return 0;
101 }
102
103 Len = 0;
104
105 while (ReverseMask != 0) {
106 ReverseMask = ReverseMask >> 1;
107 Len++;
108 }
109
110 return (UINT8) (32 - Len);
111 }
112
113
114 /**
115 Convert the hexadecimal encoded LUN string into the 64-bit LUN.
116
117 @param[in] Str The hexadecimal encoded LUN string.
118 @param[out] Lun Storage to return the 64-bit LUN.
119
120 @retval EFI_SUCCESS The 64-bit LUN is stored in Lun.
121 @retval EFI_INVALID_PARAMETER The string is malformatted.
122
123 **/
124 EFI_STATUS
125 IScsiAsciiStrToLun (
126 IN CHAR8 *Str,
127 OUT UINT8 *Lun
128 )
129 {
130 UINTN Index, IndexValue, IndexNum, SizeStr;
131 CHAR8 TemStr[2];
132 UINT8 TemValue;
133 UINT16 Value[4];
134
135 ZeroMem (Lun, 8);
136 ZeroMem (TemStr, 2);
137 ZeroMem ((UINT8 *) Value, sizeof (Value));
138 SizeStr = AsciiStrLen (Str);
139 IndexValue = 0;
140 IndexNum = 0;
141
142 for (Index = 0; Index < SizeStr; Index ++) {
143 TemStr[0] = Str[Index];
144 TemValue = (UINT8) AsciiStrHexToUint64 (TemStr);
145 if (TemValue == 0 && TemStr[0] != '0') {
146 if ((TemStr[0] != '-') || (IndexNum == 0)) {
147 //
148 // Invalid Lun Char.
149 //
150 return EFI_INVALID_PARAMETER;
151 }
152 }
153
154 if ((TemValue == 0) && (TemStr[0] == '-')) {
155 //
156 // Next Lun value.
157 //
158 if (++IndexValue >= 4) {
159 //
160 // Max 4 Lun value.
161 //
162 return EFI_INVALID_PARAMETER;
163 }
164 //
165 // Restart str index for the next lun value.
166 //
167 IndexNum = 0;
168 continue;
169 }
170
171 if (++IndexNum > 4) {
172 //
173 // Each Lun Str can't exceed size 4, because it will be as UINT16 value.
174 //
175 return EFI_INVALID_PARAMETER;
176 }
177
178 //
179 // Combine UINT16 value.
180 //
181 Value[IndexValue] = (UINT16) ((Value[IndexValue] << 4) + TemValue);
182 }
183
184 for (Index = 0; Index <= IndexValue; Index ++) {
185 *((UINT16 *) &Lun[Index * 2]) = HTONS (Value[Index]);
186 }
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 Convert the 64-bit LUN into the hexadecimal encoded LUN string.
193
194 @param[in] Lun The 64-bit LUN.
195 @param[out] Str The storage to return the hexadecimal encoded LUN string.
196
197 **/
198 VOID
199 IScsiLunToUnicodeStr (
200 IN UINT8 *Lun,
201 OUT CHAR16 *Str
202 )
203 {
204 UINTN Index;
205 CHAR16 *TempStr;
206
207 TempStr = Str;
208
209 for (Index = 0; Index < 4; Index++) {
210
211 if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {
212 CopyMem (TempStr, L"0-", sizeof (L"0-"));
213 } else {
214 TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];
215 TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0x0F];
216 TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];
217 TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0x0F];
218 TempStr[4] = L'-';
219 TempStr[5] = 0;
220
221 IScsiStrTrim (TempStr, L'0');
222 }
223
224 TempStr += StrLen (TempStr);
225 }
226 //
227 // Remove the last '-'
228 //
229 ASSERT (StrLen(Str) >= 1);
230 Str[StrLen (Str) - 1] = 0;
231
232 for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
233 if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
234 Str[Index - 1] = 0;
235 } else {
236 break;
237 }
238 }
239 }
240
241 /**
242 Convert the formatted IP address into the binary IP address.
243
244 @param[in] Str The UNICODE string.
245 @param[in] IpMode Indicates whether the IP address is v4 or v6.
246 @param[out] Ip The storage to return the ASCII string.
247
248 @retval EFI_SUCCESS The binary IP address is returned in Ip.
249 @retval EFI_INVALID_PARAMETER The IP string is malformatted or IpMode is
250 invalid.
251
252 **/
253 EFI_STATUS
254 IScsiAsciiStrToIp (
255 IN CHAR8 *Str,
256 IN UINT8 IpMode,
257 OUT EFI_IP_ADDRESS *Ip
258 )
259 {
260 EFI_STATUS Status;
261
262 if (IpMode == IP_MODE_IP4 || IpMode == IP_MODE_AUTOCONFIG_IP4) {
263 return NetLibAsciiStrToIp4 (Str, &Ip->v4);
264
265 } else if (IpMode == IP_MODE_IP6 || IpMode == IP_MODE_AUTOCONFIG_IP6) {
266 return NetLibAsciiStrToIp6 (Str, &Ip->v6);
267
268 } else if (IpMode == IP_MODE_AUTOCONFIG) {
269 Status = NetLibAsciiStrToIp4 (Str, &Ip->v4);
270 if (!EFI_ERROR (Status)) {
271 return Status;
272 }
273 return NetLibAsciiStrToIp6 (Str, &Ip->v6);
274
275 }
276
277 return EFI_INVALID_PARAMETER;
278 }
279
280 /**
281 Convert the mac address into a hexadecimal encoded "-" seperated string.
282
283 @param[in] Mac The mac address.
284 @param[in] Len Length in bytes of the mac address.
285 @param[in] VlanId VLAN ID of the network device.
286 @param[out] Str The storage to return the mac string.
287
288 **/
289 VOID
290 IScsiMacAddrToStr (
291 IN EFI_MAC_ADDRESS *Mac,
292 IN UINT32 Len,
293 IN UINT16 VlanId,
294 OUT CHAR16 *Str
295 )
296 {
297 UINT32 Index;
298 CHAR16 *String;
299
300 for (Index = 0; Index < Len; Index++) {
301 Str[3 * Index] = (CHAR16) IScsiHexString[(Mac->Addr[Index] >> 4) & 0x0F];
302 Str[3 * Index + 1] = (CHAR16) IScsiHexString[Mac->Addr[Index] & 0x0F];
303 Str[3 * Index + 2] = L':';
304 }
305
306 String = &Str[3 * Index - 1] ;
307 if (VlanId != 0) {
308 String += UnicodeSPrint (String, 6 * sizeof (CHAR16), L"\\%04x", (UINTN) VlanId);
309 }
310
311 *String = L'\0';
312 }
313
314 /**
315 Convert the binary encoded buffer into a hexadecimal encoded string.
316
317 @param[in] BinBuffer The buffer containing the binary data.
318 @param[in] BinLength Length of the binary buffer.
319 @param[in, out] HexStr Pointer to the string.
320 @param[in, out] HexLength The length of the string.
321
322 @retval EFI_SUCCESS The binary data is converted to the hexadecimal string
323 and the length of the string is updated.
324 @retval EFI_BUFFER_TOO_SMALL The string is too small.
325 @retval EFI_INVALID_PARAMETER The IP string is malformatted.
326
327 **/
328 EFI_STATUS
329 IScsiBinToHex (
330 IN UINT8 *BinBuffer,
331 IN UINT32 BinLength,
332 IN OUT CHAR8 *HexStr,
333 IN OUT UINT32 *HexLength
334 )
335 {
336 UINTN Index;
337
338 if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
339 return EFI_INVALID_PARAMETER;
340 }
341
342 if (((*HexLength) - 3) < BinLength * 2) {
343 *HexLength = BinLength * 2 + 3;
344 return EFI_BUFFER_TOO_SMALL;
345 }
346
347 *HexLength = BinLength * 2 + 3;
348 //
349 // Prefix for Hex String.
350 //
351 HexStr[0] = '0';
352 HexStr[1] = 'x';
353
354 for (Index = 0; Index < BinLength; Index++) {
355 HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
356 HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];
357 }
358
359 HexStr[Index * 2 + 2] = '\0';
360
361 return EFI_SUCCESS;
362 }
363
364
365 /**
366 Convert the hexadecimal string into a binary encoded buffer.
367
368 @param[in, out] BinBuffer The binary buffer.
369 @param[in, out] BinLength Length of the binary buffer.
370 @param[in] HexStr The hexadecimal string.
371
372 @retval EFI_SUCCESS The hexadecimal string is converted into a binary
373 encoded buffer.
374 @retval EFI_BUFFER_TOO_SMALL The binary buffer is too small to hold the converted data.
375
376 **/
377 EFI_STATUS
378 IScsiHexToBin (
379 IN OUT UINT8 *BinBuffer,
380 IN OUT UINT32 *BinLength,
381 IN CHAR8 *HexStr
382 )
383 {
384 UINTN Index;
385 UINTN Length;
386 UINT8 Digit;
387 CHAR8 TemStr[2];
388
389 ZeroMem (TemStr, sizeof (TemStr));
390
391 //
392 // Find out how many hex characters the string has.
393 //
394 if ((HexStr[0] == '0') && ((HexStr[1] == 'x') || (HexStr[1] == 'X'))) {
395 HexStr += 2;
396 }
397
398 Length = AsciiStrLen (HexStr);
399
400 for (Index = 0; Index < Length; Index ++) {
401 TemStr[0] = HexStr[Index];
402 Digit = (UINT8) AsciiStrHexToUint64 (TemStr);
403 if (Digit == 0 && TemStr[0] != '0') {
404 //
405 // Invalid Lun Char.
406 //
407 break;
408 }
409 if ((Index & 1) == 0) {
410 BinBuffer [Index/2] = Digit;
411 } else {
412 BinBuffer [Index/2] = (UINT8) ((BinBuffer [Index/2] << 4) + Digit);
413 }
414 }
415
416 *BinLength = (UINT32) ((Index + 1)/2);
417
418 return EFI_SUCCESS;
419 }
420
421
422 /**
423 Convert the decimal-constant string or hex-constant string into a numerical value.
424
425 @param[in] Str String in decimal or hex.
426
427 @return The numerical value.
428
429 **/
430 UINTN
431 IScsiNetNtoi (
432 IN CHAR8 *Str
433 )
434 {
435 if ((Str[0] == '0') && ((Str[1] == 'x') || (Str[1] == 'X'))) {
436 Str += 2;
437
438 return AsciiStrHexToUintn (Str);
439 }
440
441 return AsciiStrDecimalToUintn (Str);
442 }
443
444
445 /**
446 Generate random numbers.
447
448 @param[in, out] Rand The buffer to contain random numbers.
449 @param[in] RandLength The length of the Rand buffer.
450
451 **/
452 VOID
453 IScsiGenRandom (
454 IN OUT UINT8 *Rand,
455 IN UINTN RandLength
456 )
457 {
458 UINT32 Random;
459
460 while (RandLength > 0) {
461 Random = NET_RANDOM (NetRandomInitSeed ());
462 *Rand++ = (UINT8) (Random);
463 RandLength--;
464 }
465 }
466
467
468 /**
469 Record the NIC info in global structure.
470
471 @param[in] Controller The handle of the controller.
472
473 @retval EFI_SUCCESS The operation is completed.
474 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resources to finish this
475 operation.
476
477 **/
478 EFI_STATUS
479 IScsiAddNic (
480 IN EFI_HANDLE Controller
481 )
482 {
483 EFI_STATUS Status;
484 ISCSI_NIC_INFO *NicInfo;
485 LIST_ENTRY *Entry;
486 EFI_MAC_ADDRESS MacAddr;
487 UINTN HwAddressSize;
488 UINT16 VlanId;
489
490 //
491 // Get MAC address of this network device.
492 //
493 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
494 if (EFI_ERROR (Status)) {
495 return Status;
496 }
497
498 //
499 // Get VLAN ID of this network device.
500 //
501 VlanId = NetLibGetVlanId (Controller);
502
503 //
504 // Check whether the NIC info already exists. Return directly if so.
505 //
506 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
507 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
508 if (NicInfo->HwAddressSize == HwAddressSize &&
509 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
510 NicInfo->VlanId == VlanId) {
511 mPrivate->CurrentNic = NicInfo->NicIndex;
512 return EFI_SUCCESS;
513 }
514
515 if (mPrivate->MaxNic < NicInfo->NicIndex) {
516 mPrivate->MaxNic = NicInfo->NicIndex;
517 }
518 }
519
520 //
521 // Record the NIC info in private structure.
522 //
523 NicInfo = AllocateZeroPool (sizeof (ISCSI_NIC_INFO));
524 if (NicInfo == NULL) {
525 return EFI_OUT_OF_RESOURCES;
526 }
527
528 CopyMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize);
529 NicInfo->HwAddressSize = (UINT32) HwAddressSize;
530 NicInfo->VlanId = VlanId;
531 NicInfo->NicIndex = (UINT8) (mPrivate->MaxNic + 1);
532 mPrivate->MaxNic = NicInfo->NicIndex;
533
534 //
535 // Get the PCI location.
536 //
537 IScsiGetNICPciLocation (
538 Controller,
539 &NicInfo->BusNumber,
540 &NicInfo->DeviceNumber,
541 &NicInfo->FunctionNumber
542 );
543
544 InsertTailList (&mPrivate->NicInfoList, &NicInfo->Link);
545 mPrivate->NicCount++;
546
547 mPrivate->CurrentNic = NicInfo->NicIndex;
548 return EFI_SUCCESS;
549 }
550
551
552 /**
553 Delete the recorded NIC info from global structure. Also delete corresponding
554 attempts.
555
556 @param[in] Controller The handle of the controller.
557
558 @retval EFI_SUCCESS The operation is completed.
559 @retval EFI_NOT_FOUND The NIC info to be deleted is not recorded.
560
561 **/
562 EFI_STATUS
563 IScsiRemoveNic (
564 IN EFI_HANDLE Controller
565 )
566 {
567 EFI_STATUS Status;
568 ISCSI_NIC_INFO *NicInfo;
569 LIST_ENTRY *Entry;
570 LIST_ENTRY *NextEntry;
571 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
572 ISCSI_NIC_INFO *ThisNic;
573 EFI_MAC_ADDRESS MacAddr;
574 UINTN HwAddressSize;
575 UINT16 VlanId;
576
577 //
578 // Get MAC address of this network device.
579 //
580 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
581 if (EFI_ERROR (Status)) {
582 return Status;
583 }
584
585 //
586 // Get VLAN ID of this network device.
587 //
588 VlanId = NetLibGetVlanId (Controller);
589
590 //
591 // Check whether the NIC information exists.
592 //
593 ThisNic = NULL;
594
595 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
596 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
597 if (NicInfo->HwAddressSize == HwAddressSize &&
598 CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 &&
599 NicInfo->VlanId == VlanId) {
600
601 ThisNic = NicInfo;
602 break;
603 }
604 }
605
606 if (ThisNic == NULL) {
607 return EFI_NOT_FOUND;
608 }
609
610 mPrivate->CurrentNic = ThisNic->NicIndex;
611
612 RemoveEntryList (&ThisNic->Link);
613 FreePool (ThisNic);
614 mPrivate->NicCount--;
615
616 //
617 // Remove all attempts related to this NIC.
618 //
619 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) {
620 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link);
621 if (AttemptConfigData->NicIndex == mPrivate->CurrentNic) {
622 RemoveEntryList (&AttemptConfigData->Link);
623 mPrivate->AttemptCount--;
624
625 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO && mPrivate->MpioCount > 0) {
626 if (--mPrivate->MpioCount == 0) {
627 mPrivate->EnableMpio = FALSE;
628 }
629
630 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB && mPrivate->Krb5MpioCount > 0) {
631 mPrivate->Krb5MpioCount--;
632 }
633
634 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED && mPrivate->SinglePathCount > 0) {
635 mPrivate->SinglePathCount--;
636
637 if (mPrivate->ValidSinglePathCount > 0) {
638 mPrivate->ValidSinglePathCount--;
639 }
640 }
641
642 FreePool (AttemptConfigData);
643 }
644 }
645
646 return EFI_SUCCESS;
647 }
648
649 /**
650 Create and initialize the Attempts.
651
652 @param[in] AttemptNum The number of Attempts will be created.
653
654 @retval EFI_SUCCESS The Attempts have been created successfully.
655 @retval Others Failed to create the Attempt.
656
657 **/
658 EFI_STATUS
659 IScsiCreateAttempts (
660 IN UINTN AttemptNum
661 )
662 {
663 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
664 ISCSI_SESSION_CONFIG_NVDATA *ConfigData;
665 UINT8 *AttemptConfigOrder;
666 UINTN AttemptConfigOrderSize;
667 UINT8 *AttemptOrderTmp;
668 UINTN TotalNumber;
669 UINT8 Index;
670 EFI_STATUS Status;
671
672 for (Index = 1; Index <= AttemptNum; Index ++) {
673 //
674 // Get the initialized attempt order. This is used to essure creating attempts by order.
675 //
676 AttemptConfigOrder = IScsiGetVariableAndSize (
677 L"InitialAttemptOrder",
678 &gIScsiConfigGuid,
679 &AttemptConfigOrderSize
680 );
681 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8);
682 if (TotalNumber == AttemptNum) {
683 Status = EFI_SUCCESS;
684 break;
685 }
686 TotalNumber++;
687
688 //
689 // Append the new created attempt to the end.
690 //
691 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8));
692 if (AttemptOrderTmp == NULL) {
693 if (AttemptConfigOrder != NULL) {
694 FreePool (AttemptConfigOrder);
695 }
696 return EFI_OUT_OF_RESOURCES;
697 }
698
699 if (AttemptConfigOrder != NULL) {
700 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize);
701 FreePool (AttemptConfigOrder);
702 }
703
704 AttemptOrderTmp[TotalNumber - 1] = Index;
705 AttemptConfigOrder = AttemptOrderTmp;
706 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8);
707
708 Status = gRT->SetVariable (
709 L"InitialAttemptOrder",
710 &gIScsiConfigGuid,
711 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
712 AttemptConfigOrderSize,
713 AttemptConfigOrder
714 );
715 FreePool (AttemptConfigOrder);
716 if (EFI_ERROR (Status)) {
717 return Status;
718 }
719
720 //
721 // Create new Attempt
722 //
723 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA));
724 if (AttemptConfigData == NULL) {
725 return EFI_OUT_OF_RESOURCES;
726 }
727 ConfigData = &AttemptConfigData->SessionConfigData;
728 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT;
729 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT;
730 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY;
731
732 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP;
733 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI;
734 //
735 // Configure the Attempt index and set variable.
736 //
737 AttemptConfigData->AttemptConfigIndex = Index;
738
739 //
740 // Set the attempt name according to the order.
741 //
742 UnicodeSPrint (
743 mPrivate->PortString,
744 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
745 L"Attempt %d",
746 (UINTN) AttemptConfigData->AttemptConfigIndex
747 );
748 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, ATTEMPT_NAME_SIZE);
749
750 Status = gRT->SetVariable (
751 mPrivate->PortString,
752 &gEfiIScsiInitiatorNameProtocolGuid,
753 ISCSI_CONFIG_VAR_ATTR,
754 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
755 AttemptConfigData
756 );
757 FreePool (AttemptConfigData);
758 if (EFI_ERROR (Status)) {
759 return Status;
760 }
761 }
762
763 return EFI_SUCCESS;
764 }
765
766 /**
767 Create the iSCSI configuration Keywords for each attempt. You can find the keywords
768 defined in the "x-UEFI-ns" namespace (http://www.uefi.org/confignamespace).
769
770 @param[in] KeywordNum The number Sets of Keywords will be created.
771
772 @retval EFI_SUCCESS The operation is completed.
773 @retval Others Failed to create the Keywords.
774
775 **/
776 EFI_STATUS
777 IScsiCreateKeywords (
778 IN UINTN KeywordNum
779 )
780 {
781 VOID *StartOpCodeHandle;
782 EFI_IFR_GUID_LABEL *StartLabel;
783 VOID *EndOpCodeHandle;
784 EFI_IFR_GUID_LABEL *EndLabel;
785 UINTN Index;
786 EFI_STRING_ID StringToken;
787 CHAR16 StringId[64];
788 CHAR16 KeywordId[32];
789 EFI_STATUS Status;
790
791 Status = IScsiCreateOpCode (
792 KEYWORD_ENTRY_LABEL,
793 &StartOpCodeHandle,
794 &StartLabel,
795 &EndOpCodeHandle,
796 &EndLabel
797 );
798 if (EFI_ERROR (Status)) {
799 return EFI_OUT_OF_RESOURCES;
800 }
801
802 for (Index = 1; Index <= KeywordNum; Index ++) {
803 //
804 // Create iSCSIAttemptName Keyword.
805 //
806 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ATTEMPTT_NAME_PROMPT%d", Index);
807 StringToken = HiiSetString (
808 mCallbackInfo->RegisteredHandle,
809 0,
810 StringId,
811 NULL
812 );
813 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAttemptName:%d", Index);
814 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
815 HiiCreateStringOpCode (
816 StartOpCodeHandle,
817 (EFI_QUESTION_ID) (ATTEMPT_ATTEMPT_NAME_QUESTION_ID + (Index - 1)),
818 CONFIGURATION_VARSTORE_ID,
819 (UINT16) (ATTEMPT_ATTEMPT_NAME_VAR_OFFSET + ATTEMPT_NAME_SIZE * (Index - 1) * sizeof (CHAR16)),
820 StringToken,
821 StringToken,
822 EFI_IFR_FLAG_READ_ONLY,
823 0,
824 0,
825 ATTEMPT_NAME_SIZE,
826 NULL
827 );
828
829 //
830 // Create iSCSIBootEnable Keyword.
831 //
832 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_MODE_PROMPT%d", Index);
833 StringToken = HiiSetString (
834 mCallbackInfo->RegisteredHandle,
835 0,
836 StringId,
837 NULL
838 );
839 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIBootEnable:%d", Index);
840 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
841 HiiCreateNumericOpCode (
842 StartOpCodeHandle,
843 (EFI_QUESTION_ID) (ATTEMPT_BOOTENABLE_QUESTION_ID + (Index - 1)),
844 CONFIGURATION_VARSTORE_ID,
845 (UINT16) (ATTEMPT_BOOTENABLE_VAR_OFFSET + (Index - 1)),
846 StringToken,
847 StringToken,
848 0,
849 EFI_IFR_NUMERIC_SIZE_1,
850 0,
851 2,
852 0,
853 NULL
854 );
855
856 //
857 // Create iSCSIIpAddressType Keyword.
858 //
859 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_IP_MODE_PROMPT%d", Index);
860 StringToken = HiiSetString (
861 mCallbackInfo->RegisteredHandle,
862 0,
863 StringId,
864 NULL
865 );
866 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIIpAddressType:%d", Index);
867 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
868 HiiCreateNumericOpCode (
869 StartOpCodeHandle,
870 (EFI_QUESTION_ID) (ATTEMPT_ADDRESS_TYPE_QUESTION_ID + (Index - 1)),
871 CONFIGURATION_VARSTORE_ID,
872 (UINT16) (ATTEMPT_ADDRESS_TYPE_VAR_OFFSET + (Index - 1)),
873 StringToken,
874 StringToken,
875 0,
876 EFI_IFR_NUMERIC_SIZE_1,
877 0,
878 2,
879 0,
880 NULL
881 );
882
883 //
884 // Create iSCSIConnectRetry Keyword.
885 //
886 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_RETRY_PROMPT%d", Index);
887 StringToken = HiiSetString (
888 mCallbackInfo->RegisteredHandle,
889 0,
890 StringId,
891 NULL
892 );
893 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectRetry:%d", Index);
894 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
895 HiiCreateNumericOpCode (
896 StartOpCodeHandle,
897 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_RETRY_QUESTION_ID + (Index - 1)),
898 CONFIGURATION_VARSTORE_ID,
899 (UINT16) (ATTEMPT_CONNECT_RETRY_VAR_OFFSET + (Index - 1)),
900 StringToken,
901 StringToken,
902 0,
903 EFI_IFR_NUMERIC_SIZE_1,
904 0,
905 16,
906 0,
907 NULL
908 );
909
910 //
911 // Create iSCSIConnectTimeout Keyword.
912 //
913 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CONNECT_TIMEOUT_PROMPT%d", Index);
914 StringToken = HiiSetString (
915 mCallbackInfo->RegisteredHandle,
916 0,
917 StringId,
918 NULL
919 );
920 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIConnectTimeout:%d", Index);
921 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
922 HiiCreateNumericOpCode (
923 StartOpCodeHandle,
924 (EFI_QUESTION_ID) (ATTEMPT_CONNECT_TIMEOUT_QUESTION_ID + (Index - 1)),
925 CONFIGURATION_VARSTORE_ID,
926 (UINT16) (ATTEMPT_CONNECT_TIMEOUT_VAR_OFFSET + 2 * (Index - 1)),
927 StringToken,
928 StringToken,
929 0,
930 EFI_IFR_NUMERIC_SIZE_2,
931 CONNECT_MIN_TIMEOUT,
932 CONNECT_MAX_TIMEOUT,
933 0,
934 NULL
935 );
936
937 //
938 // Create ISID Keyword.
939 //
940 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_ISID_PROMPT%d", Index);
941 StringToken = HiiSetString (
942 mCallbackInfo->RegisteredHandle,
943 0,
944 StringId,
945 NULL
946 );
947 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIISID:%d", Index);
948 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
949 HiiCreateStringOpCode (
950 StartOpCodeHandle,
951 (EFI_QUESTION_ID) (ATTEMPT_ISID_QUESTION_ID + (Index - 1)),
952 CONFIGURATION_VARSTORE_ID,
953 (UINT16) (ATTEMPT_ISID_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
954 StringToken,
955 StringToken,
956 0,
957 0,
958 ISID_CONFIGURABLE_MIN_LEN,
959 ISID_CONFIGURABLE_STORAGE,
960 NULL
961 );
962
963 //
964 // Create iSCSIInitiatorInfoViaDHCP Keyword.
965 //
966 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_VIA_DHCP_PROMPT%d", Index);
967 StringToken = HiiSetString (
968 mCallbackInfo->RegisteredHandle,
969 0,
970 StringId,
971 NULL
972 );
973 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorInfoViaDHCP:%d", Index);
974 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
975 HiiCreateNumericOpCode (
976 StartOpCodeHandle,
977 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_VIA_DHCP_QUESTION_ID + (Index - 1)),
978 CONFIGURATION_VARSTORE_ID,
979 (UINT16) (ATTEMPT_INITIATOR_VIA_DHCP_VAR_OFFSET + (Index - 1)),
980 StringToken,
981 StringToken,
982 0,
983 0,
984 0,
985 1,
986 0,
987 NULL
988 );
989
990 //
991 // Create iSCSIInitiatorIpAddress Keyword.
992 //
993 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_IP_ADDRESS_PROMPT%d", Index);
994 StringToken = HiiSetString (
995 mCallbackInfo->RegisteredHandle,
996 0,
997 StringId,
998 NULL
999 );
1000 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorIpAddress:%d", Index);
1001 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1002 HiiCreateStringOpCode (
1003 StartOpCodeHandle,
1004 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_IP_ADDRESS_QUESTION_ID + (Index - 1)),
1005 CONFIGURATION_VARSTORE_ID,
1006 (UINT16) (ATTEMPT_INITIATOR_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1007 StringToken,
1008 StringToken,
1009 0,
1010 0,
1011 IP4_MIN_SIZE,
1012 IP4_MAX_SIZE,
1013 NULL
1014 );
1015
1016 //
1017 // Create iSCSIInitiatorNetmask Keyword.
1018 //
1019 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_NET_MASK_PROMPT%d", Index);
1020 StringToken = HiiSetString (
1021 mCallbackInfo->RegisteredHandle,
1022 0,
1023 StringId,
1024 NULL
1025 );
1026 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorNetmask:%d", Index);
1027 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1028 HiiCreateStringOpCode (
1029 StartOpCodeHandle,
1030 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_NET_MASK_QUESTION_ID + (Index - 1)),
1031 CONFIGURATION_VARSTORE_ID,
1032 (UINT16) (ATTEMPT_INITIATOR_NET_MASK_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1033 StringToken,
1034 StringToken,
1035 0,
1036 0,
1037 IP4_MIN_SIZE,
1038 IP4_MAX_SIZE,
1039 NULL
1040 );
1041
1042 //
1043 // Create iSCSIInitiatorGateway Keyword.
1044 //
1045 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_INITIATOR_GATE_PROMPT%d", Index);
1046 StringToken = HiiSetString (
1047 mCallbackInfo->RegisteredHandle,
1048 0,
1049 StringId,
1050 NULL
1051 );
1052 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIInitiatorGateway:%d", Index);
1053 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1054 HiiCreateStringOpCode (
1055 StartOpCodeHandle,
1056 (EFI_QUESTION_ID) (ATTEMPT_INITIATOR_GATE_WAY_QUESTION_ID + (Index - 1)),
1057 CONFIGURATION_VARSTORE_ID,
1058 (UINT16) (ATTEMPT_INITIATOR_GATE_WAY_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1059 StringToken,
1060 StringToken,
1061 0,
1062 0,
1063 IP4_MIN_SIZE,
1064 IP4_MAX_SIZE,
1065 NULL
1066 );
1067
1068 //
1069 // Create iSCSITargetInfoViaDHCP Keyword.
1070 //
1071 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_VIA_DHCP_PROMPT%d", Index);
1072 StringToken = HiiSetString (
1073 mCallbackInfo->RegisteredHandle,
1074 0,
1075 StringId,
1076 NULL
1077 );
1078 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetInfoViaDHCP:%d", Index);
1079 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1080 HiiCreateNumericOpCode (
1081 StartOpCodeHandle,
1082 (EFI_QUESTION_ID) (ATTEMPT_TARGET_VIA_DHCP_QUESTION_ID + (Index - 1)),
1083 CONFIGURATION_VARSTORE_ID,
1084 (UINT16) (ATTEMPT_TARGET_VIA_DHCP_VAR_OFFSET + (Index - 1)),
1085 StringToken,
1086 StringToken,
1087 0,
1088 0,
1089 0,
1090 1,
1091 0,
1092 NULL
1093 );
1094
1095 //
1096 // Create iSCSITargetTcpPort Keyword.
1097 //
1098 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_TCP_PORT_PROMPT%d", Index);
1099 StringToken = HiiSetString (
1100 mCallbackInfo->RegisteredHandle,
1101 0,
1102 StringId,
1103 NULL
1104 );
1105 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetTcpPort:%d", Index);
1106 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1107 HiiCreateNumericOpCode (
1108 StartOpCodeHandle,
1109 (EFI_QUESTION_ID) (ATTEMPT_TARGET_TCP_PORT_QUESTION_ID + (Index - 1)),
1110 CONFIGURATION_VARSTORE_ID,
1111 (UINT16) (ATTEMPT_TARGET_TCP_PORT_VAR_OFFSET + 2 * (Index - 1)),
1112 StringToken,
1113 StringToken,
1114 0,
1115 EFI_IFR_NUMERIC_SIZE_2,
1116 TARGET_PORT_MIN_NUM,
1117 TARGET_PORT_MAX_NUM,
1118 0,
1119 NULL
1120 );
1121
1122 //
1123 // Create iSCSITargetName Keyword.
1124 //
1125 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_NAME_PROMPT%d", Index);
1126 StringToken = HiiSetString (
1127 mCallbackInfo->RegisteredHandle,
1128 0,
1129 StringId,
1130 NULL
1131 );
1132 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetName:%d", Index);
1133 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1134 HiiCreateStringOpCode (
1135 StartOpCodeHandle,
1136 (EFI_QUESTION_ID) (ATTEMPT_TARGET_NAME_QUESTION_ID + (Index - 1)),
1137 CONFIGURATION_VARSTORE_ID,
1138 (UINT16) (ATTEMPT_TARGET_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1139 StringToken,
1140 StringToken,
1141 0,
1142 0,
1143 ISCSI_NAME_IFR_MIN_SIZE,
1144 ISCSI_NAME_IFR_MAX_SIZE,
1145 NULL
1146 );
1147
1148 //
1149 // Create iSCSITargetIpAddress Keyword.
1150 //
1151 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_TARGET_IP_ADDRESS_PROMPT%d", Index);
1152 StringToken = HiiSetString (
1153 mCallbackInfo->RegisteredHandle,
1154 0,
1155 StringId,
1156 NULL
1157 );
1158 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSITargetIpAddress:%d", Index);
1159 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1160 HiiCreateStringOpCode (
1161 StartOpCodeHandle,
1162 (EFI_QUESTION_ID) (ATTEMPT_TARGET_IP_ADDRESS_QUESTION_ID + (Index - 1)),
1163 CONFIGURATION_VARSTORE_ID,
1164 (UINT16) (ATTEMPT_TARGET_IP_ADDRESS_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1165 StringToken,
1166 StringToken,
1167 0,
1168 0,
1169 IP_MIN_SIZE,
1170 IP_MAX_SIZE,
1171 NULL
1172 );
1173
1174 //
1175 // Create iSCSILUN Keyword.
1176 //
1177 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_LUN_PROMPT%d", Index);
1178 StringToken = HiiSetString (
1179 mCallbackInfo->RegisteredHandle,
1180 0,
1181 StringId,
1182 NULL
1183 );
1184 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSILUN:%d", Index);
1185 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1186 HiiCreateStringOpCode (
1187 StartOpCodeHandle,
1188 (EFI_QUESTION_ID) (ATTEMPT_LUN_QUESTION_ID + (Index - 1)),
1189 CONFIGURATION_VARSTORE_ID,
1190 (UINT16) (ATTEMPT_LUN_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1191 StringToken,
1192 StringToken,
1193 0,
1194 0,
1195 LUN_MIN_SIZE,
1196 LUN_MAX_SIZE,
1197 NULL
1198 );
1199
1200 //
1201 // Create iSCSIAuthenticationMethod Keyword.
1202 //
1203 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_AUTHENTICATION_METHOD_PROMPT%d", Index);
1204 StringToken = HiiSetString (
1205 mCallbackInfo->RegisteredHandle,
1206 0,
1207 StringId,
1208 NULL
1209 );
1210 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIAuthenticationMethod:%d", Index);
1211 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1212 HiiCreateNumericOpCode (
1213 StartOpCodeHandle,
1214 (EFI_QUESTION_ID) (ATTEMPT_AUTHENTICATION_METHOD_QUESTION_ID + (Index - 1)),
1215 CONFIGURATION_VARSTORE_ID,
1216 (UINT16) (ATTEMPT_AUTHENTICATION_METHOD_VAR_OFFSET + (Index - 1)),
1217 StringToken,
1218 StringToken,
1219 0,
1220 0,
1221 0,
1222 1,
1223 0,
1224 NULL
1225 );
1226
1227 //
1228 // Create iSCSIChapType Keyword.
1229 //
1230 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHARTYPE_PROMPT%d", Index);
1231 StringToken = HiiSetString (
1232 mCallbackInfo->RegisteredHandle,
1233 0,
1234 StringId,
1235 NULL
1236 );
1237 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapType:%d", Index);
1238 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1239 HiiCreateNumericOpCode (
1240 StartOpCodeHandle,
1241 (EFI_QUESTION_ID) (ATTEMPT_CHARTYPE_QUESTION_ID + (Index - 1)),
1242 CONFIGURATION_VARSTORE_ID,
1243 (UINT16) (ATTEMPT_CHARTYPE_VAR_OFFSET + (Index - 1)),
1244 StringToken,
1245 StringToken,
1246 0,
1247 0,
1248 0,
1249 1,
1250 0,
1251 NULL
1252 );
1253
1254 //
1255 // Create iSCSIChapUsername Keyword.
1256 //
1257 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_USER_NAME_PROMPT%d", Index);
1258 StringToken = HiiSetString (
1259 mCallbackInfo->RegisteredHandle,
1260 0,
1261 StringId,
1262 NULL
1263 );
1264 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapUsername:%d", Index);
1265 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1266 HiiCreateStringOpCode (
1267 StartOpCodeHandle,
1268 (EFI_QUESTION_ID) (ATTEMPT_CHAR_USER_NAME_QUESTION_ID + (Index - 1)),
1269 CONFIGURATION_VARSTORE_ID,
1270 (UINT16) (ATTEMPT_CHAR_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1271 StringToken,
1272 StringToken,
1273 0,
1274 0,
1275 0,
1276 ISCSI_CHAP_NAME_MAX_LEN,
1277 NULL
1278 );
1279
1280 //
1281 // Create iSCSIChapSecret Keyword.
1282 //
1283 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_SECRET_PROMPT%d", Index);
1284 StringToken = HiiSetString (
1285 mCallbackInfo->RegisteredHandle,
1286 0,
1287 StringId,
1288 NULL
1289 );
1290 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIChapSecret:%d", Index);
1291 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1292 HiiCreateStringOpCode (
1293 StartOpCodeHandle,
1294 (EFI_QUESTION_ID) (ATTEMPT_CHAR_SECRET_QUESTION_ID + (Index - 1)),
1295 CONFIGURATION_VARSTORE_ID,
1296 (UINT16) (ATTEMPT_CHAR_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1297 StringToken,
1298 StringToken,
1299 0,
1300 0,
1301 ISCSI_CHAP_SECRET_MIN_LEN,
1302 ISCSI_CHAP_SECRET_MAX_LEN,
1303 NULL
1304 );
1305
1306 //
1307 // Create iSCSIReverseChapUsername Keyword.
1308 //
1309 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_USER_NAME_PROMPT%d", Index);
1310 StringToken = HiiSetString (
1311 mCallbackInfo->RegisteredHandle,
1312 0,
1313 StringId,
1314 NULL
1315 );
1316 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapUsername:%d", Index);
1317 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1318 HiiCreateStringOpCode (
1319 StartOpCodeHandle,
1320 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_USER_NAME_QUESTION_ID + (Index - 1)),
1321 CONFIGURATION_VARSTORE_ID,
1322 (UINT16) (ATTEMPT_CHAR_REVERSE_USER_NAME_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1323 StringToken,
1324 StringToken,
1325 0,
1326 0,
1327 0,
1328 ISCSI_CHAP_NAME_MAX_LEN,
1329 NULL
1330 );
1331
1332 //
1333 // Create iSCSIReverseChapSecret Keyword.
1334 //
1335 UnicodeSPrint (StringId, sizeof (StringId), L"STR_ISCSI_CHAR_REVERSE_SECRET_PROMPT%d", Index);
1336 StringToken = HiiSetString (
1337 mCallbackInfo->RegisteredHandle,
1338 0,
1339 StringId,
1340 NULL
1341 );
1342 UnicodeSPrint (KeywordId, sizeof (KeywordId), L"iSCSIReverseChapSecret:%d", Index);
1343 HiiSetString (mCallbackInfo->RegisteredHandle, StringToken, KeywordId, "x-UEFI-ns");
1344 HiiCreateStringOpCode (
1345 StartOpCodeHandle,
1346 (EFI_QUESTION_ID) (ATTEMPT_CHAR_REVERSE_SECRET_QUESTION_ID + (Index - 1)),
1347 CONFIGURATION_VARSTORE_ID,
1348 (UINT16) (ATTEMPT_CHAR_REVERSE_SECRET_VAR_OFFSET + sizeof (KEYWORD_STR) * (Index - 1)),
1349 StringToken,
1350 StringToken,
1351 0,
1352 0,
1353 ISCSI_CHAP_SECRET_MIN_LEN,
1354 ISCSI_CHAP_SECRET_MAX_LEN,
1355 NULL
1356 );
1357 }
1358
1359 Status = HiiUpdateForm (
1360 mCallbackInfo->RegisteredHandle, // HII handle
1361 &gIScsiConfigGuid, // Formset GUID
1362 FORMID_ATTEMPT_FORM, // Form ID
1363 StartOpCodeHandle, // Label for where to insert opcodes
1364 EndOpCodeHandle // Replace data
1365 );
1366
1367 HiiFreeOpCodeHandle (StartOpCodeHandle);
1368 HiiFreeOpCodeHandle (EndOpCodeHandle);
1369
1370 return Status;
1371 }
1372
1373 /**
1374
1375 Free the attempt configure data variable.
1376
1377 **/
1378 VOID
1379 IScsiCleanAttemptVariable (
1380 IN VOID
1381 )
1382 {
1383 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1384 UINT8 *AttemptConfigOrder;
1385 UINTN AttemptConfigOrderSize;
1386 UINTN Index;
1387
1388 //
1389 // Get the initialized attempt order.
1390 //
1391 AttemptConfigOrder = IScsiGetVariableAndSize (
1392 L"InitialAttemptOrder",
1393 &gIScsiConfigGuid,
1394 &AttemptConfigOrderSize
1395 );
1396 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1397 return;
1398 }
1399
1400 for (Index = 1; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1401 UnicodeSPrint (
1402 mPrivate->PortString,
1403 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1404 L"Attempt %d",
1405 Index
1406 );
1407
1408 GetVariable2 (
1409 mPrivate->PortString,
1410 &gEfiIScsiInitiatorNameProtocolGuid,
1411 (VOID**)&AttemptConfigData,
1412 NULL
1413 );
1414
1415 if (AttemptConfigData != NULL) {
1416 gRT->SetVariable (
1417 mPrivate->PortString,
1418 &gEfiIScsiInitiatorNameProtocolGuid,
1419 0,
1420 0,
1421 NULL
1422 );
1423 }
1424 }
1425 return;
1426 }
1427
1428 /**
1429 Get the recorded NIC info from global structure by the Index.
1430
1431 @param[in] NicIndex The index indicates the position of NIC info.
1432
1433 @return Pointer to the NIC info, or NULL if not found.
1434
1435 **/
1436 ISCSI_NIC_INFO *
1437 IScsiGetNicInfoByIndex (
1438 IN UINT8 NicIndex
1439 )
1440 {
1441 LIST_ENTRY *Entry;
1442 ISCSI_NIC_INFO *NicInfo;
1443
1444 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) {
1445 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link);
1446 if (NicInfo->NicIndex == NicIndex) {
1447 return NicInfo;
1448 }
1449 }
1450
1451 return NULL;
1452 }
1453
1454
1455 /**
1456 Get the NIC's PCI location and return it according to the composited
1457 format defined in iSCSI Boot Firmware Table.
1458
1459 @param[in] Controller The handle of the controller.
1460 @param[out] Bus The bus number.
1461 @param[out] Device The device number.
1462 @param[out] Function The function number.
1463
1464 @return The composited representation of the NIC PCI location.
1465
1466 **/
1467 UINT16
1468 IScsiGetNICPciLocation (
1469 IN EFI_HANDLE Controller,
1470 OUT UINTN *Bus,
1471 OUT UINTN *Device,
1472 OUT UINTN *Function
1473 )
1474 {
1475 EFI_STATUS Status;
1476 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
1477 EFI_HANDLE PciIoHandle;
1478 EFI_PCI_IO_PROTOCOL *PciIo;
1479 UINTN Segment;
1480
1481 Status = gBS->HandleProtocol (
1482 Controller,
1483 &gEfiDevicePathProtocolGuid,
1484 (VOID **) &DevicePath
1485 );
1486 if (EFI_ERROR (Status)) {
1487 return 0;
1488 }
1489
1490 Status = gBS->LocateDevicePath (
1491 &gEfiPciIoProtocolGuid,
1492 &DevicePath,
1493 &PciIoHandle
1494 );
1495 if (EFI_ERROR (Status)) {
1496 return 0;
1497 }
1498
1499 Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, (VOID **) &PciIo);
1500 if (EFI_ERROR (Status)) {
1501 return 0;
1502 }
1503
1504 Status = PciIo->GetLocation (PciIo, &Segment, Bus, Device, Function);
1505 if (EFI_ERROR (Status)) {
1506 return 0;
1507 }
1508
1509 return (UINT16) ((*Bus << 8) | (*Device << 3) | *Function);
1510 }
1511
1512
1513 /**
1514 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
1515 buffer, and the size of the buffer. If failure, return NULL.
1516
1517 @param[in] Name String part of EFI variable name.
1518 @param[in] VendorGuid GUID part of EFI variable name.
1519 @param[out] VariableSize Returns the size of the EFI variable that was read.
1520
1521 @return Dynamically allocated memory that contains a copy of the EFI variable.
1522 @return Caller is responsible freeing the buffer.
1523 @retval NULL Variable was not read.
1524
1525 **/
1526 VOID *
1527 IScsiGetVariableAndSize (
1528 IN CHAR16 *Name,
1529 IN EFI_GUID *VendorGuid,
1530 OUT UINTN *VariableSize
1531 )
1532 {
1533 EFI_STATUS Status;
1534 UINTN BufferSize;
1535 VOID *Buffer;
1536
1537 Buffer = NULL;
1538
1539 //
1540 // Pass in a zero size buffer to find the required buffer size.
1541 //
1542 BufferSize = 0;
1543 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
1544 if (Status == EFI_BUFFER_TOO_SMALL) {
1545 //
1546 // Allocate the buffer to return
1547 //
1548 Buffer = AllocateZeroPool (BufferSize);
1549 if (Buffer == NULL) {
1550 return NULL;
1551 }
1552 //
1553 // Read variable into the allocated buffer.
1554 //
1555 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
1556 if (EFI_ERROR (Status)) {
1557 BufferSize = 0;
1558 }
1559 }
1560
1561 *VariableSize = BufferSize;
1562 return Buffer;
1563 }
1564
1565
1566 /**
1567 Create the iSCSI driver data.
1568
1569 @param[in] Image The handle of the driver image.
1570 @param[in] Controller The handle of the controller.
1571
1572 @return The iSCSI driver data created.
1573 @retval NULL Other errors as indicated.
1574
1575 **/
1576 ISCSI_DRIVER_DATA *
1577 IScsiCreateDriverData (
1578 IN EFI_HANDLE Image,
1579 IN EFI_HANDLE Controller
1580 )
1581 {
1582 ISCSI_DRIVER_DATA *Private;
1583 EFI_STATUS Status;
1584
1585 Private = AllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
1586 if (Private == NULL) {
1587 return NULL;
1588 }
1589
1590 Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
1591 Private->Image = Image;
1592 Private->Controller = Controller;
1593 Private->Session = NULL;
1594
1595 //
1596 // Create an event to be signaled when the BS to RT transition is triggerd so
1597 // as to abort the iSCSI session.
1598 //
1599 Status = gBS->CreateEventEx (
1600 EVT_NOTIFY_SIGNAL,
1601 TPL_CALLBACK,
1602 IScsiOnExitBootService,
1603 Private,
1604 &gEfiEventExitBootServicesGuid,
1605 &Private->ExitBootServiceEvent
1606 );
1607 if (EFI_ERROR (Status)) {
1608 FreePool (Private);
1609 return NULL;
1610 }
1611
1612 Private->ExtScsiPassThruHandle = NULL;
1613 CopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
1614
1615 //
1616 // 0 is designated to the TargetId, so use another value for the AdapterId.
1617 //
1618 Private->ExtScsiPassThruMode.AdapterId = 2;
1619 Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
1620 Private->ExtScsiPassThruMode.IoAlign = 4;
1621 Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
1622
1623 return Private;
1624 }
1625
1626
1627 /**
1628 Clean the iSCSI driver data.
1629
1630 @param[in] Private The iSCSI driver data.
1631
1632 @retval EFI_SUCCESS The clean operation is successful.
1633 @retval Others Other errors as indicated.
1634
1635 **/
1636 EFI_STATUS
1637 IScsiCleanDriverData (
1638 IN ISCSI_DRIVER_DATA *Private
1639 )
1640 {
1641 EFI_STATUS Status;
1642
1643 Status = EFI_SUCCESS;
1644
1645 if (Private->DevicePath != NULL) {
1646 Status = gBS->UninstallProtocolInterface (
1647 Private->ExtScsiPassThruHandle,
1648 &gEfiDevicePathProtocolGuid,
1649 Private->DevicePath
1650 );
1651 if (EFI_ERROR (Status)) {
1652 goto EXIT;
1653 }
1654
1655 FreePool (Private->DevicePath);
1656 }
1657
1658 if (Private->ExtScsiPassThruHandle != NULL) {
1659 Status = gBS->UninstallProtocolInterface (
1660 Private->ExtScsiPassThruHandle,
1661 &gEfiExtScsiPassThruProtocolGuid,
1662 &Private->IScsiExtScsiPassThru
1663 );
1664 if (!EFI_ERROR (Status)) {
1665 mPrivate->OneSessionEstablished = FALSE;
1666 }
1667 }
1668
1669 EXIT:
1670
1671 gBS->CloseEvent (Private->ExitBootServiceEvent);
1672
1673 mCallbackInfo->Current = NULL;
1674
1675 FreePool (Private);
1676 return Status;
1677 }
1678
1679 /**
1680 Check wheather the Controller handle is configured to use DHCP protocol.
1681
1682 @param[in] Controller The handle of the controller.
1683 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1684
1685 @retval TRUE The handle of the controller need the Dhcp protocol.
1686 @retval FALSE The handle of the controller does not need the Dhcp protocol.
1687
1688 **/
1689 BOOLEAN
1690 IScsiDhcpIsConfigured (
1691 IN EFI_HANDLE Controller,
1692 IN UINT8 IpVersion
1693 )
1694 {
1695 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1696 UINT8 *AttemptConfigOrder;
1697 UINTN AttemptConfigOrderSize;
1698 UINTN Index;
1699 EFI_STATUS Status;
1700 EFI_MAC_ADDRESS MacAddr;
1701 UINTN HwAddressSize;
1702 UINT16 VlanId;
1703 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1704 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
1705 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
1706
1707 AttemptConfigOrder = IScsiGetVariableAndSize (
1708 L"AttemptOrder",
1709 &gIScsiConfigGuid,
1710 &AttemptConfigOrderSize
1711 );
1712 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1713 return FALSE;
1714 }
1715
1716 //
1717 // Get MAC address of this network device.
1718 //
1719 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
1720 if(EFI_ERROR (Status)) {
1721 return FALSE;
1722 }
1723 //
1724 // Get VLAN ID of this network device.
1725 //
1726 VlanId = NetLibGetVlanId (Controller);
1727 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
1728
1729 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1730 UnicodeSPrint (
1731 AttemptName,
1732 (UINTN) 128,
1733 L"Attempt %d",
1734 (UINTN) AttemptConfigOrder[Index]
1735 );
1736 Status = GetVariable2 (
1737 AttemptName,
1738 &gEfiIScsiInitiatorNameProtocolGuid,
1739 (VOID**)&AttemptTmp,
1740 NULL
1741 );
1742 if(AttemptTmp == NULL || EFI_ERROR (Status)) {
1743 continue;
1744 }
1745
1746 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);
1747
1748 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
1749 FreePool (AttemptTmp);
1750 continue;
1751 }
1752
1753 if (AttemptTmp->SessionConfigData.IpMode != IP_MODE_AUTOCONFIG &&
1754 AttemptTmp->SessionConfigData.IpMode != ((IpVersion == IP_VERSION_4) ? IP_MODE_IP4 : IP_MODE_IP6)) {
1755 FreePool (AttemptTmp);
1756 continue;
1757 }
1758
1759 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
1760
1761 if (AttemptTmp->Actived == ISCSI_ACTIVE_DISABLED || StrCmp (MacString, AttemptMacString)) {
1762 continue;
1763 }
1764
1765 if(AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG ||
1766 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp == TRUE ||
1767 AttemptTmp->SessionConfigData.TargetInfoFromDhcp == TRUE) {
1768 FreePool (AttemptTmp);
1769 FreePool (AttemptConfigOrder);
1770 return TRUE;
1771 }
1772
1773 FreePool (AttemptTmp);
1774 }
1775
1776 FreePool (AttemptConfigOrder);
1777 return FALSE;
1778 }
1779
1780 /**
1781 Check whether the Controller handle is configured to use DNS protocol.
1782
1783 @param[in] Controller The handle of the controller.
1784
1785 @retval TRUE The handle of the controller need the Dns protocol.
1786 @retval FALSE The handle of the controller does not need the Dns protocol.
1787
1788 **/
1789 BOOLEAN
1790 IScsiDnsIsConfigured (
1791 IN EFI_HANDLE Controller
1792 )
1793 {
1794 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1795 UINT8 *AttemptConfigOrder;
1796 UINTN AttemptConfigOrderSize;
1797 UINTN Index;
1798 EFI_STATUS Status;
1799 EFI_MAC_ADDRESS MacAddr;
1800 UINTN HwAddressSize;
1801 UINT16 VlanId;
1802 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
1803 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1804 CHAR16 AttemptName[ISCSI_NAME_IFR_MAX_SIZE];
1805
1806 AttemptConfigOrder = IScsiGetVariableAndSize (
1807 L"AttemptOrder",
1808 &gIScsiConfigGuid,
1809 &AttemptConfigOrderSize
1810 );
1811 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1812 return FALSE;
1813 }
1814
1815 //
1816 // Get MAC address of this network device.
1817 //
1818 Status = NetLibGetMacAddress (Controller, &MacAddr, &HwAddressSize);
1819 if(EFI_ERROR (Status)) {
1820 return FALSE;
1821 }
1822 //
1823 // Get VLAN ID of this network device.
1824 //
1825 VlanId = NetLibGetVlanId (Controller);
1826 IScsiMacAddrToStr (&MacAddr, (UINT32) HwAddressSize, VlanId, MacString);
1827
1828 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1829 UnicodeSPrint (
1830 AttemptName,
1831 (UINTN) 128,
1832 L"Attempt %d",
1833 (UINTN) AttemptConfigOrder[Index]
1834 );
1835
1836 Status = GetVariable2 (
1837 AttemptName,
1838 &gEfiIScsiInitiatorNameProtocolGuid,
1839 (VOID**)&AttemptTmp,
1840 NULL
1841 );
1842 if(AttemptTmp == NULL || EFI_ERROR (Status)) {
1843 continue;
1844 }
1845
1846 ASSERT (AttemptConfigOrder[Index] == AttemptTmp->AttemptConfigIndex);
1847
1848 AsciiStrToUnicodeStrS (AttemptTmp->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
1849
1850 if (AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED || StrCmp (MacString, AttemptMacString)) {
1851 FreePool (AttemptTmp);
1852 continue;
1853 }
1854
1855 if (AttemptTmp->SessionConfigData.DnsMode) {
1856 FreePool (AttemptTmp);
1857 FreePool (AttemptConfigOrder);
1858 return TRUE;
1859 } else {
1860 FreePool (AttemptTmp);
1861 continue;
1862 }
1863
1864 }
1865
1866 FreePool (AttemptConfigOrder);
1867 return FALSE;
1868
1869 }
1870
1871 /**
1872 Get the various configuration data.
1873
1874 @param[in] Private The iSCSI driver data.
1875
1876 @retval EFI_SUCCESS The configuration data is retrieved.
1877 @retval EFI_NOT_FOUND This iSCSI driver is not configured yet.
1878 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1879
1880 **/
1881 EFI_STATUS
1882 IScsiGetConfigData (
1883 IN ISCSI_DRIVER_DATA *Private
1884 )
1885 {
1886 EFI_STATUS Status;
1887 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN];
1888 CHAR16 AttemptMacString[ISCSI_MAX_MAC_STRING_LEN];
1889 UINTN Index;
1890 ISCSI_NIC_INFO *NicInfo;
1891 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData;
1892 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptTmp;
1893 UINT8 *AttemptConfigOrder;
1894 UINTN AttemptConfigOrderSize;
1895 CHAR16 IScsiMode[64];
1896 CHAR16 IpMode[64];
1897
1898 //
1899 // There should be at least one attempt configured.
1900 //
1901 AttemptConfigOrder = IScsiGetVariableAndSize (
1902 L"AttemptOrder",
1903 &gIScsiConfigGuid,
1904 &AttemptConfigOrderSize
1905 );
1906 if (AttemptConfigOrder == NULL || AttemptConfigOrderSize == 0) {
1907 return EFI_NOT_FOUND;
1908 }
1909
1910 //
1911 // Get the iSCSI Initiator Name.
1912 //
1913 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
1914 Status = gIScsiInitiatorName.Get (
1915 &gIScsiInitiatorName,
1916 &mPrivate->InitiatorNameLength,
1917 mPrivate->InitiatorName
1918 );
1919 if (EFI_ERROR (Status)) {
1920 return Status;
1921 }
1922
1923 //
1924 // Get the normal configuration.
1925 //
1926 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
1927
1928 //
1929 // Check whether the attempt exists in AttemptConfig.
1930 //
1931 AttemptTmp = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
1932 if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled == ISCSI_DISABLED) {
1933 continue;
1934 } else if (AttemptTmp != NULL && AttemptTmp->SessionConfigData.Enabled != ISCSI_DISABLED) {
1935 //
1936 // Check the autoconfig path to see whether it should be retried.
1937 //
1938 if (AttemptTmp->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG &&
1939 !AttemptTmp->AutoConfigureSuccess) {
1940 if (mPrivate->Ipv6Flag &&
1941 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6) {
1942 //
1943 // Autoconfigure for IP6 already attempted but failed. Do not try again.
1944 //
1945 continue;
1946 } else if (!mPrivate->Ipv6Flag &&
1947 AttemptTmp->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4) {
1948 //
1949 // Autoconfigure for IP4 already attempted but failed. Do not try again.
1950 //
1951 continue;
1952 } else {
1953 //
1954 // Try another approach for this autoconfigure path.
1955 //
1956 AttemptTmp->AutoConfigureMode =
1957 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
1958 AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
1959 AttemptTmp->SessionConfigData.TargetInfoFromDhcp = TRUE;
1960 AttemptTmp->DhcpSuccess = FALSE;
1961
1962 //
1963 // Get some information from the dhcp server.
1964 //
1965 if (!mPrivate->Ipv6Flag) {
1966 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
1967 if (!EFI_ERROR (Status)) {
1968 AttemptTmp->DhcpSuccess = TRUE;
1969 }
1970 } else {
1971 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
1972 if (!EFI_ERROR (Status)) {
1973 AttemptTmp->DhcpSuccess = TRUE;
1974 }
1975 }
1976
1977 //
1978 // Refresh the state of this attempt to NVR.
1979 //
1980 UnicodeSPrint (
1981 mPrivate->PortString,
1982 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
1983 L"Attempt %d",
1984 (UINTN) AttemptTmp->AttemptConfigIndex
1985 );
1986
1987 gRT->SetVariable (
1988 mPrivate->PortString,
1989 &gEfiIScsiInitiatorNameProtocolGuid,
1990 ISCSI_CONFIG_VAR_ATTR,
1991 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
1992 AttemptTmp
1993 );
1994
1995 continue;
1996 }
1997 } else if (AttemptTmp->SessionConfigData.InitiatorInfoFromDhcp && !AttemptTmp->ValidPath) {
1998 //
1999 // Get DHCP information for already added, but failed, attempt.
2000 //
2001 AttemptTmp->DhcpSuccess = FALSE;
2002 if (!mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP4)) {
2003 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptTmp);
2004 if (!EFI_ERROR (Status)) {
2005 AttemptTmp->DhcpSuccess = TRUE;
2006 }
2007 } else if (mPrivate->Ipv6Flag && (AttemptTmp->SessionConfigData.IpMode == IP_MODE_IP6)) {
2008 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptTmp);
2009 if (!EFI_ERROR (Status)) {
2010 AttemptTmp->DhcpSuccess = TRUE;
2011 }
2012 }
2013
2014 //
2015 // Refresh the state of this attempt to NVR.
2016 //
2017 UnicodeSPrint (
2018 mPrivate->PortString,
2019 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2020 L"Attempt %d",
2021 (UINTN) AttemptTmp->AttemptConfigIndex
2022 );
2023
2024 gRT->SetVariable (
2025 mPrivate->PortString,
2026 &gEfiIScsiInitiatorNameProtocolGuid,
2027 ISCSI_CONFIG_VAR_ATTR,
2028 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2029 AttemptTmp
2030 );
2031
2032 continue;
2033
2034 } else {
2035 continue;
2036 }
2037 }
2038
2039 //
2040 // This attempt does not exist in AttemptConfig. Try to add a new one.
2041 //
2042
2043 NicInfo = IScsiGetNicInfoByIndex (mPrivate->CurrentNic);
2044 ASSERT (NicInfo != NULL);
2045 IScsiMacAddrToStr (&NicInfo->PermanentAddress, NicInfo->HwAddressSize, NicInfo->VlanId, MacString);
2046 UnicodeSPrint (
2047 mPrivate->PortString,
2048 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2049 L"Attempt %d",
2050 (UINTN) AttemptConfigOrder[Index]
2051 );
2052
2053 GetVariable2 (
2054 mPrivate->PortString,
2055 &gEfiIScsiInitiatorNameProtocolGuid,
2056 (VOID**)&AttemptConfigData,
2057 NULL
2058 );
2059 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, AttemptMacString, sizeof (AttemptMacString) / sizeof (AttemptMacString[0]));
2060
2061 if (AttemptConfigData == NULL || AttemptConfigData->Actived == ISCSI_ACTIVE_DISABLED ||
2062 StrCmp (MacString, AttemptMacString)) {
2063 continue;
2064 }
2065
2066 ASSERT (AttemptConfigOrder[Index] == AttemptConfigData->AttemptConfigIndex);
2067
2068 AttemptConfigData->NicIndex = NicInfo->NicIndex;
2069 AttemptConfigData->DhcpSuccess = FALSE;
2070 AttemptConfigData->ValidiBFTPath = (BOOLEAN) (mPrivate->EnableMpio ? TRUE : FALSE);
2071 AttemptConfigData->ValidPath = FALSE;
2072
2073 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
2074 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp = TRUE;
2075 AttemptConfigData->SessionConfigData.TargetInfoFromDhcp = TRUE;
2076
2077 AttemptConfigData->AutoConfigureMode =
2078 (UINT8) (mPrivate->Ipv6Flag ? IP_MODE_AUTOCONFIG_IP6 : IP_MODE_AUTOCONFIG_IP4);
2079 AttemptConfigData->AutoConfigureSuccess = FALSE;
2080 }
2081
2082 //
2083 // Get some information from dhcp server.
2084 //
2085 if (AttemptConfigData->SessionConfigData.Enabled != ISCSI_DISABLED &&
2086 AttemptConfigData->SessionConfigData.InitiatorInfoFromDhcp) {
2087
2088 if (!mPrivate->Ipv6Flag &&
2089 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4 ||
2090 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP4)) {
2091 Status = IScsiDoDhcp (Private->Image, Private->Controller, AttemptConfigData);
2092 if (!EFI_ERROR (Status)) {
2093 AttemptConfigData->DhcpSuccess = TRUE;
2094 }
2095 } else if (mPrivate->Ipv6Flag &&
2096 (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6 ||
2097 AttemptConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6)) {
2098 Status = IScsiDoDhcp6 (Private->Image, Private->Controller, AttemptConfigData);
2099 if (!EFI_ERROR (Status)) {
2100 AttemptConfigData->DhcpSuccess = TRUE;
2101 }
2102 }
2103
2104 //
2105 // Refresh the state of this attempt to NVR.
2106 //
2107 UnicodeSPrint (
2108 mPrivate->PortString,
2109 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2110 L"Attempt %d",
2111 (UINTN) AttemptConfigData->AttemptConfigIndex
2112 );
2113
2114 gRT->SetVariable (
2115 mPrivate->PortString,
2116 &gEfiIScsiInitiatorNameProtocolGuid,
2117 ISCSI_CONFIG_VAR_ATTR,
2118 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA),
2119 AttemptConfigData
2120 );
2121 }
2122
2123 //
2124 // Update Attempt Help Info.
2125 //
2126
2127 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_DISABLED) {
2128 UnicodeSPrint (IScsiMode, 64, L"Disabled");
2129 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2130 UnicodeSPrint (IScsiMode, 64, L"Enabled");
2131 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2132 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO");
2133 }
2134
2135 if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP4) {
2136 UnicodeSPrint (IpMode, 64, L"IP4");
2137 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_IP6) {
2138 UnicodeSPrint (IpMode, 64, L"IP6");
2139 } else if (AttemptConfigData->SessionConfigData.IpMode == IP_MODE_AUTOCONFIG) {
2140 UnicodeSPrint (IpMode, 64, L"Autoconfigure");
2141 }
2142
2143 UnicodeSPrint (
2144 mPrivate->PortString,
2145 (UINTN) ISCSI_NAME_IFR_MAX_SIZE,
2146 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s",
2147 MacString,
2148 NicInfo->BusNumber,
2149 NicInfo->DeviceNumber,
2150 NicInfo->FunctionNumber,
2151 IScsiMode,
2152 IpMode
2153 );
2154
2155 AttemptConfigData->AttemptTitleHelpToken = HiiSetString (
2156 mCallbackInfo->RegisteredHandle,
2157 0,
2158 mPrivate->PortString,
2159 NULL
2160 );
2161 if (AttemptConfigData->AttemptTitleHelpToken == 0) {
2162 return EFI_OUT_OF_RESOURCES;
2163 }
2164
2165 //
2166 // Record the attempt in global link list.
2167 //
2168 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2169 mPrivate->AttemptCount++;
2170
2171 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) {
2172 mPrivate->MpioCount++;
2173 mPrivate->EnableMpio = TRUE;
2174
2175 if (AttemptConfigData->AuthenticationType == ISCSI_AUTH_TYPE_KRB) {
2176 mPrivate->Krb5MpioCount++;
2177 }
2178 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) {
2179 mPrivate->SinglePathCount++;
2180 }
2181 }
2182
2183 //
2184 // Reorder the AttemptConfig by the configured order.
2185 //
2186 for (Index = 0; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) {
2187 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigOrder[Index]);
2188 if (AttemptConfigData == NULL) {
2189 continue;
2190 }
2191
2192 RemoveEntryList (&AttemptConfigData->Link);
2193 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link);
2194 }
2195
2196 //
2197 // Update the Main Form.
2198 //
2199 IScsiConfigUpdateAttempt ();
2200
2201 FreePool (AttemptConfigOrder);
2202
2203 //
2204 // There should be at least one attempt configuration.
2205 //
2206 if (!mPrivate->EnableMpio) {
2207 if (mPrivate->SinglePathCount == 0) {
2208 return EFI_NOT_FOUND;
2209 }
2210 mPrivate->ValidSinglePathCount = mPrivate->SinglePathCount;
2211 }
2212
2213 return EFI_SUCCESS;
2214 }
2215
2216
2217 /**
2218 Get the device path of the iSCSI tcp connection and update it.
2219
2220 @param Session The iSCSI session.
2221
2222 @return The updated device path.
2223 @retval NULL Other errors as indicated.
2224
2225 **/
2226 EFI_DEVICE_PATH_PROTOCOL *
2227 IScsiGetTcpConnDevicePath (
2228 IN ISCSI_SESSION *Session
2229 )
2230 {
2231 ISCSI_CONNECTION *Conn;
2232 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2233 EFI_STATUS Status;
2234 EFI_DEV_PATH *DPathNode;
2235 UINTN PathLen;
2236
2237 if (Session->State != SESSION_STATE_LOGGED_IN) {
2238 return NULL;
2239 }
2240
2241 Conn = NET_LIST_USER_STRUCT_S (
2242 Session->Conns.ForwardLink,
2243 ISCSI_CONNECTION,
2244 Link,
2245 ISCSI_CONNECTION_SIGNATURE
2246 );
2247
2248 Status = gBS->HandleProtocol (
2249 Conn->TcpIo.Handle,
2250 &gEfiDevicePathProtocolGuid,
2251 (VOID **) &DevicePath
2252 );
2253 if (EFI_ERROR (Status)) {
2254 return NULL;
2255 }
2256 //
2257 // Duplicate it.
2258 //
2259 DevicePath = DuplicateDevicePath (DevicePath);
2260 if (DevicePath == NULL) {
2261 return NULL;
2262 }
2263
2264 DPathNode = (EFI_DEV_PATH *) DevicePath;
2265
2266 while (!IsDevicePathEnd (&DPathNode->DevPath)) {
2267 if (DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) {
2268 if (!Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP) {
2269 DPathNode->Ipv4.LocalPort = 0;
2270
2271 DPathNode->Ipv4.StaticIpAddress =
2272 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
2273
2274 //
2275 // Add a judgement here to support previous versions of IPv4_DEVICE_PATH.
2276 // In previous versions of IPv4_DEVICE_PATH, GatewayIpAddress and SubnetMask
2277 // do not exist.
2278 // In new version of IPv4_DEVICE_PATH, structcure length is 27.
2279 //
2280
2281 PathLen = DevicePathNodeLength (&DPathNode->Ipv4);
2282
2283 if (PathLen == IP4_NODE_LEN_NEW_VERSIONS) {
2284
2285 IP4_COPY_ADDRESS (
2286 &DPathNode->Ipv4.GatewayIpAddress,
2287 &Session->ConfigData->SessionConfigData.Gateway
2288 );
2289
2290 IP4_COPY_ADDRESS (
2291 &DPathNode->Ipv4.SubnetMask,
2292 &Session->ConfigData->SessionConfigData.SubnetMask
2293 );
2294 }
2295
2296 break;
2297 } else if (Conn->Ipv6Flag && DevicePathSubType (&DPathNode->DevPath) == MSG_IPv6_DP) {
2298 DPathNode->Ipv6.LocalPort = 0;
2299
2300 //
2301 // Add a judgement here to support previous versions of IPv6_DEVICE_PATH.
2302 // In previous versions of IPv6_DEVICE_PATH, IpAddressOrigin, PrefixLength
2303 // and GatewayIpAddress do not exist.
2304 // In new version of IPv6_DEVICE_PATH, structure length is 60, while in
2305 // old versions, the length is 43.
2306 //
2307
2308 PathLen = DevicePathNodeLength (&DPathNode->Ipv6);
2309
2310 if (PathLen == IP6_NODE_LEN_NEW_VERSIONS ) {
2311
2312 DPathNode->Ipv6.IpAddressOrigin = 0;
2313 DPathNode->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;
2314 ZeroMem (&DPathNode->Ipv6.GatewayIpAddress, sizeof (EFI_IPv6_ADDRESS));
2315 }
2316 else if (PathLen == IP6_NODE_LEN_OLD_VERSIONS) {
2317
2318 //
2319 // StaticIPAddress is a field in old versions of IPv6_DEVICE_PATH, while ignored in new
2320 // version. Set StaticIPAddress through its' offset in old IPv6_DEVICE_PATH.
2321 //
2322 *((UINT8 *)(&DPathNode->Ipv6) + IP6_OLD_IPADDRESS_OFFSET) =
2323 (BOOLEAN) (!Session->ConfigData->SessionConfigData.InitiatorInfoFromDhcp);
2324 }
2325
2326 break;
2327 }
2328 }
2329
2330 DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
2331 }
2332
2333 return DevicePath;
2334 }
2335
2336
2337 /**
2338 Abort the session when the transition from BS to RT is initiated.
2339
2340 @param[in] Event The event signaled.
2341 @param[in] Context The iSCSI driver data.
2342
2343 **/
2344 VOID
2345 EFIAPI
2346 IScsiOnExitBootService (
2347 IN EFI_EVENT Event,
2348 IN VOID *Context
2349 )
2350 {
2351 ISCSI_DRIVER_DATA *Private;
2352
2353 Private = (ISCSI_DRIVER_DATA *) Context;
2354 gBS->CloseEvent (Private->ExitBootServiceEvent);
2355
2356 if (Private->Session != NULL) {
2357 IScsiSessionAbort (Private->Session);
2358 }
2359 }
2360
2361 /**
2362 Tests whether a controller handle is being managed by IScsi driver.
2363
2364 This function tests whether the driver specified by DriverBindingHandle is
2365 currently managing the controller specified by ControllerHandle. This test
2366 is performed by evaluating if the the protocol specified by ProtocolGuid is
2367 present on ControllerHandle and is was opened by DriverBindingHandle and Nic
2368 Device handle with an attribute of EFI_OPEN_PROTOCOL_BY_DRIVER.
2369 If ProtocolGuid is NULL, then ASSERT().
2370
2371 @param ControllerHandle A handle for a controller to test.
2372 @param DriverBindingHandle Specifies the driver binding handle for the
2373 driver.
2374 @param ProtocolGuid Specifies the protocol that the driver specified
2375 by DriverBindingHandle opens in its Start()
2376 function.
2377
2378 @retval EFI_SUCCESS ControllerHandle is managed by the driver
2379 specified by DriverBindingHandle.
2380 @retval EFI_UNSUPPORTED ControllerHandle is not managed by the driver
2381 specified by DriverBindingHandle.
2382
2383 **/
2384 EFI_STATUS
2385 EFIAPI
2386 IScsiTestManagedDevice (
2387 IN EFI_HANDLE ControllerHandle,
2388 IN EFI_HANDLE DriverBindingHandle,
2389 IN EFI_GUID *ProtocolGuid
2390 )
2391 {
2392 EFI_STATUS Status;
2393 VOID *ManagedInterface;
2394 EFI_HANDLE NicControllerHandle;
2395
2396 ASSERT (ProtocolGuid != NULL);
2397
2398 NicControllerHandle = NetLibGetNicHandle (ControllerHandle, ProtocolGuid);
2399 if (NicControllerHandle == NULL) {
2400 return EFI_UNSUPPORTED;
2401 }
2402
2403 Status = gBS->OpenProtocol (
2404 ControllerHandle,
2405 (EFI_GUID *) ProtocolGuid,
2406 &ManagedInterface,
2407 DriverBindingHandle,
2408 NicControllerHandle,
2409 EFI_OPEN_PROTOCOL_BY_DRIVER
2410 );
2411 if (!EFI_ERROR (Status)) {
2412 gBS->CloseProtocol (
2413 ControllerHandle,
2414 (EFI_GUID *) ProtocolGuid,
2415 DriverBindingHandle,
2416 NicControllerHandle
2417 );
2418 return EFI_UNSUPPORTED;
2419 }
2420
2421 if (Status != EFI_ALREADY_STARTED) {
2422 return EFI_UNSUPPORTED;
2423 }
2424
2425 return EFI_SUCCESS;
2426 }