1 /** @file 2 Helper functions for configuring or getting the parameters relating to iSCSI. 3 4 Copyright (c) 2004 - 2016, 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 CHAR16 mVendorStorageName[] = L"ISCSI_CONFIG_IFR_NVDATA"; 18 BOOLEAN mIScsiDeviceListUpdated = FALSE; 19 UINTN mNumberOfIScsiDevices = 0; 20 ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL; 21 22 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath = { 23 { 24 { 25 HARDWARE_DEVICE_PATH, 26 HW_VENDOR_DP, 27 { 28 (UINT8) (sizeof (VENDOR_DEVICE_PATH)), 29 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) 30 } 31 }, 32 ISCSI_CONFIG_GUID 33 }, 34 { 35 END_DEVICE_PATH_TYPE, 36 END_ENTIRE_DEVICE_PATH_SUBTYPE, 37 { 38 (UINT8) (END_DEVICE_PATH_LENGTH), 39 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) 40 } 41 } 42 }; 43 44 45 /** 46 Convert the IP address into a dotted string. 47 48 @param[in] Ip The IP address. 49 @param[in] Ipv6Flag Indicates whether the IP address is version 4 or version 6. 50 @param[out] Str The formatted IP string. 51 52 **/ 53 VOID 54 IScsiIpToStr ( 55 IN EFI_IP_ADDRESS *Ip, 56 IN BOOLEAN Ipv6Flag, 57 OUT CHAR16 *Str 58 ) 59 { 60 EFI_IPv4_ADDRESS *Ip4; 61 EFI_IPv6_ADDRESS *Ip6; 62 UINTN Index; 63 BOOLEAN Short; 64 UINTN Number; 65 CHAR16 FormatString[8]; 66 67 if (!Ipv6Flag) { 68 Ip4 = &Ip->v4; 69 70 UnicodeSPrint ( 71 Str, 72 (UINTN) 2 * IP4_STR_MAX_SIZE, 73 L"%d.%d.%d.%d", 74 (UINTN) Ip4->Addr[0], 75 (UINTN) Ip4->Addr[1], 76 (UINTN) Ip4->Addr[2], 77 (UINTN) Ip4->Addr[3] 78 ); 79 80 return ; 81 } 82 83 Ip6 = &Ip->v6; 84 Short = FALSE; 85 86 for (Index = 0; Index < 15; Index = Index + 2) { 87 if (!Short && 88 Index % 2 == 0 && 89 Ip6->Addr[Index] == 0 && 90 Ip6->Addr[Index + 1] == 0 91 ) { 92 // 93 // Deal with the case of ::. 94 // 95 if (Index == 0) { 96 *Str = L':'; 97 *(Str + 1) = L':'; 98 Str = Str + 2; 99 } else { 100 *Str = L':'; 101 Str = Str + 1; 102 } 103 104 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) { 105 Index = Index + 2; 106 } 107 108 Short = TRUE; 109 110 if (Index == 16) { 111 // 112 // :: is at the end of the address. 113 // 114 *Str = L'\0'; 115 break; 116 } 117 } 118 119 ASSERT (Index < 15); 120 121 if (Ip6->Addr[Index] == 0) { 122 Number = UnicodeSPrint (Str, 2 * IP_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]); 123 } else { 124 if (Ip6->Addr[Index + 1] < 0x10) { 125 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:")); 126 } else { 127 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:")); 128 } 129 130 Number = UnicodeSPrint ( 131 Str, 132 2 * IP_STR_MAX_SIZE, 133 (CONST CHAR16 *) FormatString, 134 (UINTN) Ip6->Addr[Index], 135 (UINTN) Ip6->Addr[Index + 1] 136 ); 137 } 138 139 Str = Str + Number; 140 141 if (Index + 2 == 16) { 142 *Str = L'\0'; 143 if (*(Str - 1) == L':') { 144 *(Str - 1) = L'\0'; 145 } 146 } 147 } 148 } 149 150 /** 151 Check whether the input IP address is valid. 152 153 @param[in] Ip The IP address. 154 @param[in] IpMode Indicates iSCSI running on IP4 or IP6 stack. 155 156 @retval TRUE The input IP address is valid. 157 @retval FALSE Otherwise 158 159 **/ 160 BOOLEAN 161 IpIsUnicast ( 162 IN EFI_IP_ADDRESS *Ip, 163 IN UINT8 IpMode 164 ) 165 { 166 if (IpMode == IP_MODE_IP4) { 167 if (IP4_IS_UNSPECIFIED (NTOHL (Ip->Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip->Addr[0]))) { 168 return FALSE; 169 } 170 return TRUE; 171 } else if (IpMode == IP_MODE_IP6) { 172 return NetIp6IsValidUnicast (&Ip->v6); 173 } else { 174 DEBUG ((DEBUG_ERROR, "IpMode %d is invalid when configuring the iSCSI target IP!\n", IpMode)); 175 return FALSE; 176 } 177 } 178 179 /** 180 Parse IsId in string format and convert it to binary. 181 182 @param[in] String The buffer of the string to be parsed. 183 @param[in, out] IsId The buffer to store IsId. 184 185 @retval EFI_SUCCESS The operation finished successfully. 186 @retval EFI_INVALID_PARAMETER Any input parameter is invalid. 187 188 **/ 189 EFI_STATUS 190 IScsiParseIsIdFromString ( 191 IN CONST CHAR16 *String, 192 IN OUT UINT8 *IsId 193 ) 194 { 195 UINT8 Index; 196 CHAR16 *IsIdStr; 197 CHAR16 TempStr[3]; 198 UINTN NodeVal; 199 CHAR16 PortString[ISCSI_NAME_IFR_MAX_SIZE]; 200 EFI_INPUT_KEY Key; 201 202 if ((String == NULL) || (IsId == NULL)) { 203 return EFI_INVALID_PARAMETER; 204 } 205 206 IsIdStr = (CHAR16 *) String; 207 208 if (StrLen (IsIdStr) != 6) { 209 UnicodeSPrint ( 210 PortString, 211 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 212 L"Error! Input is incorrect, please input 6 hex numbers!\n" 213 ); 214 215 CreatePopUp ( 216 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 217 &Key, 218 PortString, 219 NULL 220 ); 221 222 return EFI_INVALID_PARAMETER; 223 } 224 225 for (Index = 3; Index < 6; Index++) { 226 CopyMem (TempStr, IsIdStr, sizeof (TempStr)); 227 TempStr[2] = L'\0'; 228 229 // 230 // Convert the string to IsId. StrHexToUintn stops at the first character 231 // that is not a valid hex character, '\0' here. 232 // 233 NodeVal = StrHexToUintn (TempStr); 234 235 IsId[Index] = (UINT8) NodeVal; 236 237 IsIdStr = IsIdStr + 2; 238 } 239 240 return EFI_SUCCESS; 241 } 242 243 /** 244 Convert IsId from binary to string format. 245 246 @param[out] String The buffer to store the converted string. 247 @param[in] IsId The buffer to store IsId. 248 249 @retval EFI_SUCCESS The string converted successfully. 250 @retval EFI_INVALID_PARAMETER Any input parameter is invalid. 251 252 **/ 253 EFI_STATUS 254 IScsiConvertIsIdToString ( 255 OUT CHAR16 *String, 256 IN UINT8 *IsId 257 ) 258 { 259 UINT8 Index; 260 UINTN Number; 261 262 if ((String == NULL) || (IsId == NULL)) { 263 return EFI_INVALID_PARAMETER; 264 } 265 266 for (Index = 0; Index < 6; Index++) { 267 if (IsId[Index] <= 0xF) { 268 Number = UnicodeSPrint ( 269 String, 270 2 * ISID_CONFIGURABLE_STORAGE, 271 L"0%X", 272 (UINTN) IsId[Index] 273 ); 274 } else { 275 Number = UnicodeSPrint ( 276 String, 277 2 * ISID_CONFIGURABLE_STORAGE, 278 L"%X", 279 (UINTN) IsId[Index] 280 ); 281 282 } 283 284 String = String + Number; 285 } 286 287 *String = L'\0'; 288 289 return EFI_SUCCESS; 290 } 291 292 /** 293 Get the attempt config data from global structure by the ConfigIndex. 294 295 @param[in] AttemptConfigIndex The unique index indicates the attempt. 296 297 @return Pointer to the attempt config data. 298 @retval NULL The attempt configuration data cannot be found. 299 300 **/ 301 ISCSI_ATTEMPT_CONFIG_NVDATA * 302 IScsiConfigGetAttemptByConfigIndex ( 303 IN UINT8 AttemptConfigIndex 304 ) 305 { 306 LIST_ENTRY *Entry; 307 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt; 308 309 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) { 310 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); 311 if (Attempt->AttemptConfigIndex == AttemptConfigIndex) { 312 return Attempt; 313 } 314 } 315 316 return NULL; 317 } 318 319 320 /** 321 Get the existing attempt config data from global structure by the NicIndex. 322 323 @param[in] NewAttempt The created new attempt 324 @param[in] IScsiMode The IScsi Mode of the new attempt, Enabled or 325 Enabled for MPIO. 326 327 @return Pointer to the existing attempt config data which 328 has the same NICIndex as the new created attempt. 329 @retval NULL The attempt with NicIndex does not exist. 330 331 **/ 332 ISCSI_ATTEMPT_CONFIG_NVDATA * 333 IScsiConfigGetAttemptByNic ( 334 IN ISCSI_ATTEMPT_CONFIG_NVDATA *NewAttempt, 335 IN UINT8 IScsiMode 336 ) 337 { 338 LIST_ENTRY *Entry; 339 ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt; 340 341 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) { 342 Attempt = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); 343 if (Attempt != NewAttempt && Attempt->NicIndex == NewAttempt->NicIndex && 344 Attempt->SessionConfigData.Enabled == IScsiMode) { 345 return Attempt; 346 } 347 } 348 349 return NULL; 350 } 351 352 353 /** 354 Convert the iSCSI configuration data into the IFR data. 355 356 @param[in] Attempt The iSCSI attempt config data. 357 @param[in, out] IfrNvData The IFR nv data. 358 359 **/ 360 VOID 361 IScsiConvertAttemptConfigDataToIfrNvData ( 362 IN ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt, 363 IN OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData 364 ) 365 { 366 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData; 367 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData; 368 EFI_IP_ADDRESS Ip; 369 370 // 371 // Normal session configuration parameters. 372 // 373 SessionConfigData = &Attempt->SessionConfigData; 374 IfrNvData->Enabled = SessionConfigData->Enabled; 375 IfrNvData->IpMode = SessionConfigData->IpMode; 376 377 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp; 378 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp; 379 IfrNvData->TargetPort = SessionConfigData->TargetPort; 380 381 if (IfrNvData->IpMode == IP_MODE_IP4) { 382 CopyMem (&Ip.v4, &SessionConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS)); 383 IScsiIpToStr (&Ip, FALSE, IfrNvData->LocalIp); 384 CopyMem (&Ip.v4, &SessionConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); 385 IScsiIpToStr (&Ip, FALSE, IfrNvData->SubnetMask); 386 CopyMem (&Ip.v4, &SessionConfigData->Gateway, sizeof (EFI_IPv4_ADDRESS)); 387 IScsiIpToStr (&Ip, FALSE, IfrNvData->Gateway); 388 CopyMem (&Ip.v4, &SessionConfigData->TargetIp, sizeof (EFI_IPv4_ADDRESS)); 389 IScsiIpToStr (&Ip, FALSE, IfrNvData->TargetIp); 390 } else if (IfrNvData->IpMode == IP_MODE_IP6) { 391 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp)); 392 IP6_COPY_ADDRESS (&Ip.v6, &SessionConfigData->TargetIp); 393 IScsiIpToStr (&Ip, TRUE, IfrNvData->TargetIp); 394 } 395 396 AsciiStrToUnicodeStrS ( 397 SessionConfigData->TargetName, 398 IfrNvData->TargetName, 399 sizeof (IfrNvData->TargetName) / sizeof (IfrNvData->TargetName[0]) 400 ); 401 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun); 402 IScsiConvertIsIdToString (IfrNvData->IsId, SessionConfigData->IsId); 403 404 IfrNvData->ConnectRetryCount = SessionConfigData->ConnectRetryCount; 405 IfrNvData->ConnectTimeout = SessionConfigData->ConnectTimeout; 406 407 // 408 // Authentication parameters. 409 // 410 IfrNvData->AuthenticationType = Attempt->AuthenticationType; 411 412 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) { 413 AuthConfigData = &Attempt->AuthConfigData.CHAP; 414 IfrNvData->CHAPType = AuthConfigData->CHAPType; 415 AsciiStrToUnicodeStrS ( 416 AuthConfigData->CHAPName, 417 IfrNvData->CHAPName, 418 sizeof (IfrNvData->CHAPName) / sizeof (IfrNvData->CHAPName[0]) 419 ); 420 AsciiStrToUnicodeStrS ( 421 AuthConfigData->CHAPSecret, 422 IfrNvData->CHAPSecret, 423 sizeof (IfrNvData->CHAPSecret) / sizeof (IfrNvData->CHAPSecret[0]) 424 ); 425 AsciiStrToUnicodeStrS ( 426 AuthConfigData->ReverseCHAPName, 427 IfrNvData->ReverseCHAPName, 428 sizeof (IfrNvData->ReverseCHAPName) / sizeof (IfrNvData->ReverseCHAPName[0]) 429 ); 430 AsciiStrToUnicodeStrS ( 431 AuthConfigData->ReverseCHAPSecret, 432 IfrNvData->ReverseCHAPSecret, 433 sizeof (IfrNvData->ReverseCHAPSecret) / sizeof (IfrNvData->ReverseCHAPSecret[0]) 434 ); 435 } 436 437 // 438 // Other parameters. 439 // 440 AsciiStrToUnicodeStrS ( 441 Attempt->AttemptName, 442 IfrNvData->AttemptName, 443 sizeof (IfrNvData->AttemptName) / sizeof (IfrNvData->AttemptName[0]) 444 ); 445 } 446 447 /** 448 Convert the IFR data to iSCSI configuration data. 449 450 @param[in] IfrNvData Point to ISCSI_CONFIG_IFR_NVDATA. 451 @param[in, out] Attempt The iSCSI attempt config data. 452 453 @retval EFI_INVALID_PARAMETER Any input or configured parameter is invalid. 454 @retval EFI_NOT_FOUND Cannot find the corresponding variable. 455 @retval EFI_OUT_OF_RESOURCES The operation is failed due to lack of resources. 456 @retval EFI_ABORTED The operation is aborted. 457 @retval EFI_SUCCESS The operation is completed successfully. 458 459 **/ 460 EFI_STATUS 461 IScsiConvertIfrNvDataToAttemptConfigData ( 462 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData, 463 IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *Attempt 464 ) 465 { 466 EFI_IP_ADDRESS HostIp; 467 EFI_IP_ADDRESS SubnetMask; 468 EFI_IP_ADDRESS Gateway; 469 CHAR16 *MacString; 470 CHAR16 *AttemptName1; 471 CHAR16 *AttemptName2; 472 ISCSI_ATTEMPT_CONFIG_NVDATA *ExistAttempt; 473 ISCSI_ATTEMPT_CONFIG_NVDATA *SameNicAttempt; 474 CHAR16 IScsiMode[64]; 475 CHAR16 IpMode[64]; 476 ISCSI_NIC_INFO *NicInfo; 477 EFI_INPUT_KEY Key; 478 UINT8 *AttemptConfigOrder; 479 UINTN AttemptConfigOrderSize; 480 UINT8 *AttemptOrderTmp; 481 UINTN TotalNumber; 482 EFI_STATUS Status; 483 484 if (IfrNvData == NULL || Attempt == NULL) { 485 return EFI_INVALID_PARAMETER; 486 } 487 488 // 489 // Update those fields which don't have INTERACTIVE attribute. 490 // 491 Attempt->SessionConfigData.ConnectRetryCount = IfrNvData->ConnectRetryCount; 492 Attempt->SessionConfigData.ConnectTimeout = IfrNvData->ConnectTimeout; 493 Attempt->SessionConfigData.IpMode = IfrNvData->IpMode; 494 495 if (IfrNvData->IpMode < IP_MODE_AUTOCONFIG) { 496 Attempt->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp; 497 Attempt->SessionConfigData.TargetPort = IfrNvData->TargetPort; 498 499 if (Attempt->SessionConfigData.TargetPort == 0) { 500 Attempt->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT; 501 } 502 503 Attempt->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp; 504 } 505 506 Attempt->AuthenticationType = IfrNvData->AuthenticationType; 507 508 if (Attempt->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) { 509 Attempt->AuthConfigData.CHAP.CHAPType = IfrNvData->CHAPType; 510 } 511 512 // 513 // Only do full parameter validation if iSCSI is enabled on this device. 514 // 515 if (IfrNvData->Enabled != ISCSI_DISABLED) { 516 if (Attempt->SessionConfigData.ConnectTimeout < CONNECT_MIN_TIMEOUT) { 517 CreatePopUp ( 518 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 519 &Key, 520 L"Connection Establishing Timeout is less than minimum value 100ms.", 521 NULL 522 ); 523 524 return EFI_INVALID_PARAMETER; 525 } 526 527 // 528 // Validate the address configuration of the Initiator if DHCP isn't 529 // deployed. 530 // 531 if (!Attempt->SessionConfigData.InitiatorInfoFromDhcp) { 532 CopyMem (&HostIp.v4, &Attempt->SessionConfigData.LocalIp, sizeof (HostIp.v4)); 533 CopyMem (&SubnetMask.v4, &Attempt->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4)); 534 CopyMem (&Gateway.v4, &Attempt->SessionConfigData.Gateway, sizeof (Gateway.v4)); 535 536 if ((Gateway.Addr[0] != 0)) { 537 if (SubnetMask.Addr[0] == 0) { 538 CreatePopUp ( 539 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 540 &Key, 541 L"Gateway address is set but subnet mask is zero.", 542 NULL 543 ); 544 545 return EFI_INVALID_PARAMETER; 546 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) { 547 CreatePopUp ( 548 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 549 &Key, 550 L"Local IP and Gateway are not in the same subnet.", 551 NULL 552 ); 553 554 return EFI_INVALID_PARAMETER; 555 } 556 } 557 } 558 // 559 // Validate target configuration if DHCP isn't deployed. 560 // 561 if (!Attempt->SessionConfigData.TargetInfoFromDhcp && Attempt->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) { 562 if (!IpIsUnicast (&Attempt->SessionConfigData.TargetIp, IfrNvData->IpMode)) { 563 CreatePopUp ( 564 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 565 &Key, 566 L"Target IP is invalid!", 567 NULL 568 ); 569 return EFI_INVALID_PARAMETER; 570 } 571 572 // 573 // Validate iSCSI target name configuration again: 574 // The format of iSCSI target name is already verified in IScsiFormCallback() when 575 // user input the name; here we only check the case user does not input the name. 576 // 577 if (Attempt->SessionConfigData.TargetName[0] == '\0') { 578 CreatePopUp ( 579 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 580 &Key, 581 L"iSCSI target name is NULL!", 582 NULL 583 ); 584 return EFI_INVALID_PARAMETER; 585 } 586 } 587 588 589 // 590 // Validate the authentication info. 591 // 592 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) { 593 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) { 594 CreatePopUp ( 595 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 596 &Key, 597 L"CHAP Name or CHAP Secret is invalid!", 598 NULL 599 ); 600 601 return EFI_INVALID_PARAMETER; 602 } 603 604 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) && 605 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0')) 606 ) { 607 CreatePopUp ( 608 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 609 &Key, 610 L"Reverse CHAP Name or Reverse CHAP Secret is invalid!", 611 NULL 612 ); 613 return EFI_INVALID_PARAMETER; 614 } 615 } 616 617 // 618 // Check whether this attempt uses NIC which is already used by existing attempt. 619 // 620 SameNicAttempt = IScsiConfigGetAttemptByNic (Attempt, IfrNvData->Enabled); 621 if (SameNicAttempt != NULL) { 622 AttemptName1 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16)); 623 if (AttemptName1 == NULL) { 624 return EFI_OUT_OF_RESOURCES; 625 } 626 627 AttemptName2 = (CHAR16 *) AllocateZeroPool (ATTEMPT_NAME_MAX_SIZE * sizeof (CHAR16)); 628 if (AttemptName2 == NULL) { 629 FreePool (AttemptName1); 630 return EFI_OUT_OF_RESOURCES; 631 } 632 633 AsciiStrToUnicodeStrS (Attempt->AttemptName, AttemptName1, ATTEMPT_NAME_MAX_SIZE); 634 if (StrLen (AttemptName1) > ATTEMPT_NAME_SIZE) { 635 CopyMem (&AttemptName1[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16)); 636 } 637 638 AsciiStrToUnicodeStrS (SameNicAttempt->AttemptName, AttemptName2, ATTEMPT_NAME_MAX_SIZE); 639 if (StrLen (AttemptName2) > ATTEMPT_NAME_SIZE) { 640 CopyMem (&AttemptName2[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16)); 641 } 642 643 UnicodeSPrint ( 644 mPrivate->PortString, 645 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 646 L"Warning! Attempt \"%s\" uses same NIC as Attempt \"%s\".", 647 AttemptName1, 648 AttemptName2 649 ); 650 651 CreatePopUp ( 652 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 653 &Key, 654 mPrivate->PortString, 655 NULL 656 ); 657 658 FreePool (AttemptName1); 659 FreePool (AttemptName2); 660 } 661 } 662 663 // 664 // Update the iSCSI Mode data and record it in attempt help info. 665 // 666 Attempt->SessionConfigData.Enabled = IfrNvData->Enabled; 667 if (IfrNvData->Enabled == ISCSI_DISABLED) { 668 UnicodeSPrint (IScsiMode, 64, L"Disabled"); 669 } else if (IfrNvData->Enabled == ISCSI_ENABLED) { 670 UnicodeSPrint (IScsiMode, 64, L"Enabled"); 671 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) { 672 UnicodeSPrint (IScsiMode, 64, L"Enabled for MPIO"); 673 } 674 675 if (IfrNvData->IpMode == IP_MODE_IP4) { 676 UnicodeSPrint (IpMode, 64, L"IP4"); 677 } else if (IfrNvData->IpMode == IP_MODE_IP6) { 678 UnicodeSPrint (IpMode, 64, L"IP6"); 679 } else if (IfrNvData->IpMode == IP_MODE_AUTOCONFIG) { 680 UnicodeSPrint (IpMode, 64, L"Autoconfigure"); 681 } 682 683 NicInfo = IScsiGetNicInfoByIndex (Attempt->NicIndex); 684 if (NicInfo == NULL) { 685 return EFI_NOT_FOUND; 686 } 687 688 MacString = (CHAR16 *) AllocateZeroPool (ISCSI_MAX_MAC_STRING_LEN * sizeof (CHAR16)); 689 if (MacString == NULL) { 690 return EFI_OUT_OF_RESOURCES; 691 } 692 693 AsciiStrToUnicodeStrS (Attempt->MacString, MacString, ISCSI_MAX_MAC_STRING_LEN); 694 695 UnicodeSPrint ( 696 mPrivate->PortString, 697 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 698 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d, iSCSI mode: %s, IP version: %s", 699 MacString, 700 NicInfo->BusNumber, 701 NicInfo->DeviceNumber, 702 NicInfo->FunctionNumber, 703 IScsiMode, 704 IpMode 705 ); 706 707 Attempt->AttemptTitleHelpToken = HiiSetString ( 708 mCallbackInfo->RegisteredHandle, 709 Attempt->AttemptTitleHelpToken, 710 mPrivate->PortString, 711 NULL 712 ); 713 if (Attempt->AttemptTitleHelpToken == 0) { 714 FreePool (MacString); 715 return EFI_OUT_OF_RESOURCES; 716 } 717 718 // 719 // Check whether this attempt is an existing one. 720 // 721 ExistAttempt = IScsiConfigGetAttemptByConfigIndex (Attempt->AttemptConfigIndex); 722 if (ExistAttempt != NULL) { 723 ASSERT (ExistAttempt == Attempt); 724 725 if (IfrNvData->Enabled == ISCSI_DISABLED && 726 Attempt->SessionConfigData.Enabled != ISCSI_DISABLED) { 727 728 // 729 // User updates the Attempt from "Enabled"/"Enabled for MPIO" to "Disabled". 730 // 731 if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) { 732 if (mPrivate->MpioCount < 1) { 733 return EFI_ABORTED; 734 } 735 736 if (--mPrivate->MpioCount == 0) { 737 mPrivate->EnableMpio = FALSE; 738 } 739 } else if (Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) { 740 if (mPrivate->SinglePathCount < 1) { 741 return EFI_ABORTED; 742 } 743 mPrivate->SinglePathCount--; 744 } 745 746 } else if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO && 747 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED) { 748 // 749 // User updates the Attempt from "Enabled" to "Enabled for MPIO". 750 // 751 if (mPrivate->SinglePathCount < 1) { 752 return EFI_ABORTED; 753 } 754 755 mPrivate->EnableMpio = TRUE; 756 mPrivate->MpioCount++; 757 mPrivate->SinglePathCount--; 758 759 } else if (IfrNvData->Enabled == ISCSI_ENABLED && 760 Attempt->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) { 761 // 762 // User updates the Attempt from "Enabled for MPIO" to "Enabled". 763 // 764 if (mPrivate->MpioCount < 1) { 765 return EFI_ABORTED; 766 } 767 768 if (--mPrivate->MpioCount == 0) { 769 mPrivate->EnableMpio = FALSE; 770 } 771 mPrivate->SinglePathCount++; 772 773 } else if (IfrNvData->Enabled != ISCSI_DISABLED && 774 Attempt->SessionConfigData.Enabled == ISCSI_DISABLED) { 775 // 776 // User updates the Attempt from "Disabled" to "Enabled"/"Enabled for MPIO". 777 // 778 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) { 779 mPrivate->EnableMpio = TRUE; 780 mPrivate->MpioCount++; 781 782 } else if (IfrNvData->Enabled == ISCSI_ENABLED) { 783 mPrivate->SinglePathCount++; 784 } 785 } 786 787 } else if (ExistAttempt == NULL) { 788 // 789 // When a new attempt is created, pointer of the attempt is saved to 790 // mPrivate->NewAttempt, and also saved to mCallbackInfo->Current in 791 // IScsiConfigProcessDefault. If input Attempt does not match any existing 792 // attempt, it should be a new created attempt. Save it to system now. 793 // 794 ASSERT (Attempt == mPrivate->NewAttempt); 795 796 // 797 // Save current order number for this attempt. 798 // 799 AttemptConfigOrder = IScsiGetVariableAndSize ( 800 L"AttemptOrder", 801 &gIScsiConfigGuid, 802 &AttemptConfigOrderSize 803 ); 804 805 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8); 806 TotalNumber++; 807 808 // 809 // Append the new created attempt order to the end. 810 // 811 AttemptOrderTmp = AllocateZeroPool (TotalNumber * sizeof (UINT8)); 812 if (AttemptOrderTmp == NULL) { 813 if (AttemptConfigOrder != NULL) { 814 FreePool (AttemptConfigOrder); 815 } 816 return EFI_OUT_OF_RESOURCES; 817 } 818 819 if (AttemptConfigOrder != NULL) { 820 CopyMem (AttemptOrderTmp, AttemptConfigOrder, AttemptConfigOrderSize); 821 FreePool (AttemptConfigOrder); 822 } 823 824 AttemptOrderTmp[TotalNumber - 1] = Attempt->AttemptConfigIndex; 825 AttemptConfigOrder = AttemptOrderTmp; 826 AttemptConfigOrderSize = TotalNumber * sizeof (UINT8); 827 828 Status = gRT->SetVariable ( 829 L"AttemptOrder", 830 &gIScsiConfigGuid, 831 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, 832 AttemptConfigOrderSize, 833 AttemptConfigOrder 834 ); 835 FreePool (AttemptConfigOrder); 836 if (EFI_ERROR (Status)) { 837 return Status; 838 } 839 840 // 841 // Insert new created attempt to array. 842 // 843 InsertTailList (&mPrivate->AttemptConfigs, &Attempt->Link); 844 mPrivate->AttemptCount++; 845 // 846 // Reset mPrivate->NewAttempt to NULL, which indicates none attempt is created 847 // but not saved now. 848 // 849 mPrivate->NewAttempt = NULL; 850 851 if (IfrNvData->Enabled == ISCSI_ENABLED_FOR_MPIO) { 852 // 853 // This new Attempt is enabled for MPIO; enable the multipath mode. 854 // 855 mPrivate->EnableMpio = TRUE; 856 mPrivate->MpioCount++; 857 } else if (IfrNvData->Enabled == ISCSI_ENABLED) { 858 mPrivate->SinglePathCount++; 859 } 860 861 IScsiConfigUpdateAttempt (); 862 } 863 864 // 865 // Record the user configuration information in NVR. 866 // 867 UnicodeSPrint ( 868 mPrivate->PortString, 869 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 870 L"%s%d", 871 MacString, 872 (UINTN) Attempt->AttemptConfigIndex 873 ); 874 875 FreePool (MacString); 876 877 return gRT->SetVariable ( 878 mPrivate->PortString, 879 &gEfiIScsiInitiatorNameProtocolGuid, 880 ISCSI_CONFIG_VAR_ATTR, 881 sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA), 882 Attempt 883 ); 884 } 885 886 /** 887 Create Hii Extend Label OpCode as the start opcode and end opcode. It is 888 a help function. 889 890 @param[in] StartLabelNumber The number of start label. 891 @param[out] StartOpCodeHandle Points to the start opcode handle. 892 @param[out] StartLabel Points to the created start opcode. 893 @param[out] EndOpCodeHandle Points to the end opcode handle. 894 @param[out] EndLabel Points to the created end opcode. 895 896 @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this 897 operation. 898 @retval EFI_INVALID_PARAMETER Any input parameter is invalid. 899 @retval EFI_SUCCESS The operation is completed successfully. 900 901 **/ 902 EFI_STATUS 903 IScsiCreateOpCode ( 904 IN UINT16 StartLabelNumber, 905 OUT VOID **StartOpCodeHandle, 906 OUT EFI_IFR_GUID_LABEL **StartLabel, 907 OUT VOID **EndOpCodeHandle, 908 OUT EFI_IFR_GUID_LABEL **EndLabel 909 ) 910 { 911 EFI_STATUS Status; 912 EFI_IFR_GUID_LABEL *InternalStartLabel; 913 EFI_IFR_GUID_LABEL *InternalEndLabel; 914 915 if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) { 916 return EFI_INVALID_PARAMETER; 917 } 918 919 *StartOpCodeHandle = NULL; 920 *EndOpCodeHandle = NULL; 921 Status = EFI_OUT_OF_RESOURCES; 922 923 // 924 // Initialize the container for dynamic opcodes. 925 // 926 *StartOpCodeHandle = HiiAllocateOpCodeHandle (); 927 if (*StartOpCodeHandle == NULL) { 928 return Status; 929 } 930 931 *EndOpCodeHandle = HiiAllocateOpCodeHandle (); 932 if (*EndOpCodeHandle == NULL) { 933 goto Exit; 934 } 935 936 // 937 // Create Hii Extend Label OpCode as the start opcode. 938 // 939 InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( 940 *StartOpCodeHandle, 941 &gEfiIfrTianoGuid, 942 NULL, 943 sizeof (EFI_IFR_GUID_LABEL) 944 ); 945 if (InternalStartLabel == NULL) { 946 goto Exit; 947 } 948 949 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 950 InternalStartLabel->Number = StartLabelNumber; 951 952 // 953 // Create Hii Extend Label OpCode as the end opcode. 954 // 955 InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( 956 *EndOpCodeHandle, 957 &gEfiIfrTianoGuid, 958 NULL, 959 sizeof (EFI_IFR_GUID_LABEL) 960 ); 961 if (InternalEndLabel == NULL) { 962 goto Exit; 963 } 964 965 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; 966 InternalEndLabel->Number = LABEL_END; 967 968 *StartLabel = InternalStartLabel; 969 *EndLabel = InternalEndLabel; 970 971 return EFI_SUCCESS; 972 973 Exit: 974 975 if (*StartOpCodeHandle != NULL) { 976 HiiFreeOpCodeHandle (*StartOpCodeHandle); 977 } 978 979 if (*EndOpCodeHandle != NULL) { 980 HiiFreeOpCodeHandle (*EndOpCodeHandle); 981 } 982 983 return Status; 984 } 985 986 /** 987 Callback function when user presses "Add an Attempt". 988 989 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this 990 operation. 991 @retval EFI_SUCCESS The operation is completed successfully. 992 993 **/ 994 EFI_STATUS 995 IScsiConfigAddAttempt ( 996 VOID 997 ) 998 { 999 LIST_ENTRY *Entry; 1000 ISCSI_NIC_INFO *NicInfo; 1001 EFI_STRING_ID PortTitleToken; 1002 EFI_STRING_ID PortTitleHelpToken; 1003 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN]; 1004 EFI_STATUS Status; 1005 VOID *StartOpCodeHandle; 1006 EFI_IFR_GUID_LABEL *StartLabel; 1007 VOID *EndOpCodeHandle; 1008 EFI_IFR_GUID_LABEL *EndLabel; 1009 1010 Status = IScsiCreateOpCode ( 1011 MAC_ENTRY_LABEL, 1012 &StartOpCodeHandle, 1013 &StartLabel, 1014 &EndOpCodeHandle, 1015 &EndLabel 1016 ); 1017 if (EFI_ERROR (Status)) { 1018 return Status; 1019 } 1020 1021 // 1022 // Ask user to select a MAC for this attempt. 1023 // 1024 NET_LIST_FOR_EACH (Entry, &mPrivate->NicInfoList) { 1025 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link); 1026 IScsiMacAddrToStr ( 1027 &NicInfo->PermanentAddress, 1028 NicInfo->HwAddressSize, 1029 NicInfo->VlanId, 1030 MacString 1031 ); 1032 1033 UnicodeSPrint (mPrivate->PortString, (UINTN) ISCSI_NAME_IFR_MAX_SIZE, L"MAC %s", MacString); 1034 PortTitleToken = HiiSetString ( 1035 mCallbackInfo->RegisteredHandle, 1036 0, 1037 mPrivate->PortString, 1038 NULL 1039 ); 1040 if (PortTitleToken == 0) { 1041 Status = EFI_INVALID_PARAMETER; 1042 goto Exit; 1043 } 1044 1045 UnicodeSPrint ( 1046 mPrivate->PortString, 1047 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 1048 L"PFA: Bus %d | Dev %d | Func %d", 1049 NicInfo->BusNumber, 1050 NicInfo->DeviceNumber, 1051 NicInfo->FunctionNumber 1052 ); 1053 PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, mPrivate->PortString, NULL); 1054 if (PortTitleHelpToken == 0) { 1055 Status = EFI_INVALID_PARAMETER; 1056 goto Exit; 1057 } 1058 1059 HiiCreateGotoOpCode ( 1060 StartOpCodeHandle, // Container for dynamic created opcodes 1061 FORMID_ATTEMPT_FORM, 1062 PortTitleToken, 1063 PortTitleHelpToken, 1064 EFI_IFR_FLAG_CALLBACK, // Question flag 1065 (UINT16) (KEY_MAC_ENTRY_BASE + NicInfo->NicIndex) 1066 ); 1067 } 1068 1069 Status = HiiUpdateForm ( 1070 mCallbackInfo->RegisteredHandle, // HII handle 1071 &gIScsiConfigGuid, // Formset GUID 1072 FORMID_MAC_FORM, // Form ID 1073 StartOpCodeHandle, // Label for where to insert opcodes 1074 EndOpCodeHandle // Replace data 1075 ); 1076 1077 Exit: 1078 HiiFreeOpCodeHandle (StartOpCodeHandle); 1079 HiiFreeOpCodeHandle (EndOpCodeHandle); 1080 1081 return Status; 1082 } 1083 1084 1085 /** 1086 Update the MAIN form to display the configured attempts. 1087 1088 **/ 1089 VOID 1090 IScsiConfigUpdateAttempt ( 1091 VOID 1092 ) 1093 { 1094 CHAR16 AttemptName[ATTEMPT_NAME_MAX_SIZE]; 1095 LIST_ENTRY *Entry; 1096 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 1097 VOID *StartOpCodeHandle; 1098 EFI_IFR_GUID_LABEL *StartLabel; 1099 VOID *EndOpCodeHandle; 1100 EFI_IFR_GUID_LABEL *EndLabel; 1101 EFI_STATUS Status; 1102 1103 Status = IScsiCreateOpCode ( 1104 ATTEMPT_ENTRY_LABEL, 1105 &StartOpCodeHandle, 1106 &StartLabel, 1107 &EndOpCodeHandle, 1108 &EndLabel 1109 ); 1110 if (EFI_ERROR (Status)) { 1111 return ; 1112 } 1113 1114 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) { 1115 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); 1116 1117 AsciiStrToUnicodeStrS (AttemptConfigData->AttemptName, AttemptName, ARRAY_SIZE (AttemptName)); 1118 UnicodeSPrint (mPrivate->PortString, (UINTN) 128, L"Attempt %s", AttemptName); 1119 AttemptConfigData->AttemptTitleToken = HiiSetString ( 1120 mCallbackInfo->RegisteredHandle, 1121 0, 1122 mPrivate->PortString, 1123 NULL 1124 ); 1125 if (AttemptConfigData->AttemptTitleToken == 0) { 1126 return ; 1127 } 1128 1129 HiiCreateGotoOpCode ( 1130 StartOpCodeHandle, // Container for dynamic created opcodes 1131 FORMID_ATTEMPT_FORM, // Form ID 1132 AttemptConfigData->AttemptTitleToken, // Prompt text 1133 AttemptConfigData->AttemptTitleHelpToken, // Help text 1134 EFI_IFR_FLAG_CALLBACK, // Question flag 1135 (UINT16) (KEY_ATTEMPT_ENTRY_BASE + AttemptConfigData->AttemptConfigIndex) // Question ID 1136 ); 1137 } 1138 1139 HiiUpdateForm ( 1140 mCallbackInfo->RegisteredHandle, // HII handle 1141 &gIScsiConfigGuid, // Formset GUID 1142 FORMID_MAIN_FORM, // Form ID 1143 StartOpCodeHandle, // Label for where to insert opcodes 1144 EndOpCodeHandle // Replace data 1145 ); 1146 1147 HiiFreeOpCodeHandle (StartOpCodeHandle); 1148 HiiFreeOpCodeHandle (EndOpCodeHandle); 1149 } 1150 1151 1152 /** 1153 Callback function when user presses "Commit Changes and Exit" in Delete Attempts. 1154 1155 @param[in] IfrNvData The IFR NV data. 1156 1157 @retval EFI_NOT_FOUND Cannot find the corresponding variable. 1158 @retval EFI_SUCCESS The operation is completed successfully. 1159 @retval EFI_ABOTRED This operation is aborted cause of error 1160 configuration. 1161 @retval EFI_OUT_OF_RESOURCES Fail to finish the operation due to lack of 1162 resources. 1163 1164 **/ 1165 EFI_STATUS 1166 IScsiConfigDeleteAttempts ( 1167 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData 1168 ) 1169 { 1170 EFI_STATUS Status; 1171 UINTN Index; 1172 UINTN NewIndex; 1173 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 1174 UINT8 *AttemptConfigOrder; 1175 UINTN AttemptConfigOrderSize; 1176 UINT8 *AttemptNewOrder; 1177 UINT32 Attribute; 1178 UINTN Total; 1179 UINTN NewTotal; 1180 LIST_ENTRY *Entry; 1181 LIST_ENTRY *NextEntry; 1182 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN]; 1183 1184 AttemptConfigOrder = IScsiGetVariableAndSize ( 1185 L"AttemptOrder", 1186 &gIScsiConfigGuid, 1187 &AttemptConfigOrderSize 1188 ); 1189 if ((AttemptConfigOrder == NULL) || (AttemptConfigOrderSize == 0)) { 1190 return EFI_NOT_FOUND; 1191 } 1192 1193 AttemptNewOrder = AllocateZeroPool (AttemptConfigOrderSize); 1194 if (AttemptNewOrder == NULL) { 1195 Status = EFI_OUT_OF_RESOURCES; 1196 goto Error; 1197 } 1198 1199 Total = AttemptConfigOrderSize / sizeof (UINT8); 1200 NewTotal = Total; 1201 Index = 0; 1202 1203 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mPrivate->AttemptConfigs) { 1204 if (IfrNvData->DeleteAttemptList[Index] == 0) { 1205 Index++; 1206 continue; 1207 } 1208 1209 // 1210 // Delete the attempt. 1211 // 1212 1213 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); 1214 if (AttemptConfigData == NULL) { 1215 Status = EFI_NOT_FOUND; 1216 goto Error; 1217 } 1218 1219 // 1220 // Remove this attempt from UI configured attempt list. 1221 // 1222 RemoveEntryList (&AttemptConfigData->Link); 1223 mPrivate->AttemptCount--; 1224 1225 if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED_FOR_MPIO) { 1226 if (mPrivate->MpioCount < 1) { 1227 Status = EFI_ABORTED; 1228 goto Error; 1229 } 1230 1231 // 1232 // No more attempt is enabled for MPIO. Transit the iSCSI mode to single path. 1233 // 1234 if (--mPrivate->MpioCount == 0) { 1235 mPrivate->EnableMpio = FALSE; 1236 } 1237 } else if (AttemptConfigData->SessionConfigData.Enabled == ISCSI_ENABLED) { 1238 if (mPrivate->SinglePathCount < 1) { 1239 Status = EFI_ABORTED; 1240 goto Error; 1241 } 1242 1243 mPrivate->SinglePathCount--; 1244 } 1245 1246 AsciiStrToUnicodeStrS (AttemptConfigData->MacString, MacString, ARRAY_SIZE (MacString)); 1247 1248 UnicodeSPrint ( 1249 mPrivate->PortString, 1250 (UINTN) 128, 1251 L"%s%d", 1252 MacString, 1253 (UINTN) AttemptConfigData->AttemptConfigIndex 1254 ); 1255 1256 gRT->SetVariable ( 1257 mPrivate->PortString, 1258 &gEfiIScsiInitiatorNameProtocolGuid, 1259 0, 1260 0, 1261 NULL 1262 ); 1263 1264 // 1265 // Mark the attempt order in NVR to be deleted - 0. 1266 // 1267 for (NewIndex = 0; NewIndex < Total; NewIndex++) { 1268 if (AttemptConfigOrder[NewIndex] == AttemptConfigData->AttemptConfigIndex) { 1269 AttemptConfigOrder[NewIndex] = 0; 1270 break; 1271 } 1272 } 1273 1274 NewTotal--; 1275 FreePool (AttemptConfigData); 1276 1277 // 1278 // Check next Attempt. 1279 // 1280 Index++; 1281 } 1282 1283 // 1284 // Construct AttemptNewOrder. 1285 // 1286 for (Index = 0, NewIndex = 0; Index < Total; Index++) { 1287 if (AttemptConfigOrder[Index] != 0) { 1288 AttemptNewOrder[NewIndex] = AttemptConfigOrder[Index]; 1289 NewIndex++; 1290 } 1291 } 1292 1293 Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE; 1294 1295 // 1296 // Update AttemptOrder in NVR. 1297 // 1298 Status = gRT->SetVariable ( 1299 L"AttemptOrder", 1300 &gIScsiConfigGuid, 1301 Attribute, 1302 NewTotal * sizeof (UINT8), 1303 AttemptNewOrder 1304 ); 1305 1306 Error: 1307 if (AttemptConfigOrder != NULL) { 1308 FreePool (AttemptConfigOrder); 1309 } 1310 1311 if (AttemptNewOrder != NULL) { 1312 FreePool (AttemptNewOrder); 1313 } 1314 1315 return Status; 1316 } 1317 1318 1319 /** 1320 Callback function when user presses "Delete Attempts". 1321 1322 @param[in] IfrNvData The IFR nv data. 1323 1324 @retval EFI_INVALID_PARAMETER Any parameter is invalid. 1325 @retval EFI_BUFFER_TOO_SMALL The buffer in UpdateData is too small. 1326 @retval EFI_SUCCESS The operation is completed successfully. 1327 1328 **/ 1329 EFI_STATUS 1330 IScsiConfigDisplayDeleteAttempts ( 1331 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData 1332 ) 1333 { 1334 1335 UINT8 *AttemptConfigOrder; 1336 UINTN AttemptConfigOrderSize; 1337 LIST_ENTRY *Entry; 1338 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 1339 UINT8 Index; 1340 VOID *StartOpCodeHandle; 1341 EFI_IFR_GUID_LABEL *StartLabel; 1342 VOID *EndOpCodeHandle; 1343 EFI_IFR_GUID_LABEL *EndLabel; 1344 EFI_STATUS Status; 1345 1346 Status = IScsiCreateOpCode ( 1347 DELETE_ENTRY_LABEL, 1348 &StartOpCodeHandle, 1349 &StartLabel, 1350 &EndOpCodeHandle, 1351 &EndLabel 1352 ); 1353 if (EFI_ERROR (Status)) { 1354 return Status; 1355 } 1356 1357 AttemptConfigOrder = IScsiGetVariableAndSize ( 1358 L"AttemptOrder", 1359 &gIScsiConfigGuid, 1360 &AttemptConfigOrderSize 1361 ); 1362 if (AttemptConfigOrder != NULL) { 1363 // 1364 // Create the check box opcode to be deleted. 1365 // 1366 Index = 0; 1367 1368 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) { 1369 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); 1370 IfrNvData->DeleteAttemptList[Index] = 0x00; 1371 1372 HiiCreateCheckBoxOpCode( 1373 StartOpCodeHandle, 1374 (EFI_QUESTION_ID) (ATTEMPT_DEL_QUESTION_ID + Index), 1375 CONFIGURATION_VARSTORE_ID, 1376 (UINT16) (ATTEMPT_DEL_VAR_OFFSET + Index), 1377 AttemptConfigData->AttemptTitleToken, 1378 AttemptConfigData->AttemptTitleHelpToken, 1379 0, 1380 0, 1381 NULL 1382 ); 1383 1384 Index++; 1385 1386 if (Index == ISCSI_MAX_ATTEMPTS_NUM) { 1387 break; 1388 } 1389 } 1390 1391 FreePool (AttemptConfigOrder); 1392 } 1393 1394 Status = HiiUpdateForm ( 1395 mCallbackInfo->RegisteredHandle, // HII handle 1396 &gIScsiConfigGuid, // Formset GUID 1397 FORMID_DELETE_FORM, // Form ID 1398 StartOpCodeHandle, // Label for where to insert opcodes 1399 EndOpCodeHandle // Replace data 1400 ); 1401 1402 HiiFreeOpCodeHandle (StartOpCodeHandle); 1403 HiiFreeOpCodeHandle (EndOpCodeHandle); 1404 1405 return Status; 1406 } 1407 1408 1409 /** 1410 Callback function when user presses "Change Attempt Order". 1411 1412 @retval EFI_INVALID_PARAMETER Any parameter is invalid. 1413 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this 1414 operation. 1415 @retval EFI_SUCCESS The operation is completed successfully. 1416 1417 **/ 1418 EFI_STATUS 1419 IScsiConfigDisplayOrderAttempts ( 1420 VOID 1421 ) 1422 { 1423 EFI_STATUS Status; 1424 UINT8 Index; 1425 LIST_ENTRY *Entry; 1426 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 1427 VOID *StartOpCodeHandle; 1428 EFI_IFR_GUID_LABEL *StartLabel; 1429 VOID *EndOpCodeHandle; 1430 EFI_IFR_GUID_LABEL *EndLabel; 1431 VOID *OptionsOpCodeHandle; 1432 1433 Status = IScsiCreateOpCode ( 1434 ORDER_ENTRY_LABEL, 1435 &StartOpCodeHandle, 1436 &StartLabel, 1437 &EndOpCodeHandle, 1438 &EndLabel 1439 ); 1440 if (EFI_ERROR (Status)) { 1441 return Status; 1442 } 1443 ASSERT (StartOpCodeHandle != NULL); 1444 1445 OptionsOpCodeHandle = NULL; 1446 1447 // 1448 // If no attempt to be ordered, update the original form and exit. 1449 // 1450 if (mPrivate->AttemptCount == 0) { 1451 goto Exit; 1452 } 1453 1454 // 1455 // Create Option OpCode. 1456 // 1457 OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); 1458 if (OptionsOpCodeHandle == NULL) { 1459 Status = EFI_OUT_OF_RESOURCES; 1460 goto Error; 1461 } 1462 1463 Index = 0; 1464 1465 NET_LIST_FOR_EACH (Entry, &mPrivate->AttemptConfigs) { 1466 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); 1467 HiiCreateOneOfOptionOpCode ( 1468 OptionsOpCodeHandle, 1469 AttemptConfigData->AttemptTitleToken, 1470 0, 1471 EFI_IFR_NUMERIC_SIZE_1, 1472 AttemptConfigData->AttemptConfigIndex 1473 ); 1474 Index++; 1475 } 1476 1477 ASSERT (Index == mPrivate->AttemptCount); 1478 1479 HiiCreateOrderedListOpCode ( 1480 StartOpCodeHandle, // Container for dynamic created opcodes 1481 DYNAMIC_ORDERED_LIST_QUESTION_ID, // Question ID 1482 CONFIGURATION_VARSTORE_ID, // VarStore ID 1483 DYNAMIC_ORDERED_LIST_VAR_OFFSET, // Offset in Buffer Storage 1484 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question prompt text 1485 STRING_TOKEN (STR_ORDER_ATTEMPT_ENTRY), // Question help text 1486 0, // Question flag 1487 EFI_IFR_UNIQUE_SET, // Ordered list flag, e.g. EFI_IFR_UNIQUE_SET 1488 EFI_IFR_NUMERIC_SIZE_1, // Data type of Question value 1489 ISCSI_MAX_ATTEMPTS_NUM, // Maximum container 1490 OptionsOpCodeHandle, // Option Opcode list 1491 NULL // Default Opcode is NULL 1492 ); 1493 1494 Exit: 1495 Status = HiiUpdateForm ( 1496 mCallbackInfo->RegisteredHandle, // HII handle 1497 &gIScsiConfigGuid, // Formset GUID 1498 FORMID_ORDER_FORM, // Form ID 1499 StartOpCodeHandle, // Label for where to insert opcodes 1500 EndOpCodeHandle // Replace data 1501 ); 1502 1503 Error: 1504 HiiFreeOpCodeHandle (StartOpCodeHandle); 1505 HiiFreeOpCodeHandle (EndOpCodeHandle); 1506 if (OptionsOpCodeHandle != NULL) { 1507 HiiFreeOpCodeHandle (OptionsOpCodeHandle); 1508 } 1509 1510 return Status; 1511 } 1512 1513 1514 /** 1515 Callback function when user presses "Commit Changes and Exit" in Change Attempt Order. 1516 1517 @param[in] IfrNvData The IFR nv data. 1518 1519 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this 1520 operation. 1521 @retval EFI_NOT_FOUND Cannot find the corresponding variable. 1522 @retval EFI_SUCCESS The operation is completed successfully. 1523 1524 **/ 1525 EFI_STATUS 1526 IScsiConfigOrderAttempts ( 1527 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData 1528 ) 1529 { 1530 EFI_STATUS Status; 1531 UINTN Index; 1532 UINTN Indexj; 1533 UINT8 AttemptConfigIndex; 1534 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 1535 UINT8 *AttemptConfigOrder; 1536 UINT8 *AttemptConfigOrderTmp; 1537 UINTN AttemptConfigOrderSize; 1538 1539 AttemptConfigOrder = IScsiGetVariableAndSize ( 1540 L"AttemptOrder", 1541 &gIScsiConfigGuid, 1542 &AttemptConfigOrderSize 1543 ); 1544 if (AttemptConfigOrder == NULL) { 1545 return EFI_NOT_FOUND; 1546 } 1547 1548 AttemptConfigOrderTmp = AllocateZeroPool (AttemptConfigOrderSize); 1549 if (AttemptConfigOrderTmp == NULL) { 1550 Status = EFI_OUT_OF_RESOURCES; 1551 goto Exit; 1552 } 1553 1554 for (Index = 0; Index < ISCSI_MAX_ATTEMPTS_NUM; Index++) { 1555 // 1556 // The real content ends with 0. 1557 // 1558 if (IfrNvData->DynamicOrderedList[Index] == 0) { 1559 break; 1560 } 1561 1562 AttemptConfigIndex = IfrNvData->DynamicOrderedList[Index]; 1563 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (AttemptConfigIndex); 1564 if (AttemptConfigData == NULL) { 1565 Status = EFI_NOT_FOUND; 1566 goto Exit; 1567 } 1568 1569 // 1570 // Reorder the Attempt List. 1571 // 1572 RemoveEntryList (&AttemptConfigData->Link); 1573 InsertTailList (&mPrivate->AttemptConfigs, &AttemptConfigData->Link); 1574 1575 AttemptConfigOrderTmp[Index] = AttemptConfigIndex; 1576 1577 // 1578 // Mark it to be deleted - 0. 1579 // 1580 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) { 1581 if (AttemptConfigOrder[Indexj] == AttemptConfigIndex) { 1582 AttemptConfigOrder[Indexj] = 0; 1583 break; 1584 } 1585 } 1586 } 1587 1588 // 1589 // Adjust the attempt order in NVR. 1590 // 1591 for (; Index < AttemptConfigOrderSize / sizeof (UINT8); Index++) { 1592 for (Indexj = 0; Indexj < AttemptConfigOrderSize / sizeof (UINT8); Indexj++) { 1593 if (AttemptConfigOrder[Indexj] != 0) { 1594 AttemptConfigOrderTmp[Index] = AttemptConfigOrder[Indexj]; 1595 AttemptConfigOrder[Indexj] = 0; 1596 continue; 1597 } 1598 } 1599 } 1600 1601 Status = gRT->SetVariable ( 1602 L"AttemptOrder", 1603 &gIScsiConfigGuid, 1604 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, 1605 AttemptConfigOrderSize, 1606 AttemptConfigOrderTmp 1607 ); 1608 1609 Exit: 1610 if (AttemptConfigOrderTmp != NULL) { 1611 FreePool (AttemptConfigOrderTmp); 1612 } 1613 1614 FreePool (AttemptConfigOrder); 1615 return Status; 1616 } 1617 1618 1619 /** 1620 Callback function when a user presses "Attempt *" or when a user selects a NIC to 1621 create the new attempt. 1622 1623 @param[in] KeyValue A unique value which is sent to the original 1624 exporting driver so that it can identify the type 1625 of data to expect. 1626 @param[in] IfrNvData The IFR nv data. 1627 1628 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this 1629 operation. 1630 @retval EFI_NOT_FOUND Cannot find the corresponding variable. 1631 @retval EFI_SUCCESS The operation is completed successfully. 1632 1633 **/ 1634 EFI_STATUS 1635 IScsiConfigProcessDefault ( 1636 IN EFI_QUESTION_ID KeyValue, 1637 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData 1638 ) 1639 { 1640 BOOLEAN NewAttempt; 1641 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 1642 ISCSI_SESSION_CONFIG_NVDATA *ConfigData; 1643 UINT8 CurrentAttemptConfigIndex; 1644 ISCSI_NIC_INFO *NicInfo; 1645 UINT8 NicIndex; 1646 CHAR16 MacString[ISCSI_MAX_MAC_STRING_LEN]; 1647 UINT8 *AttemptConfigOrder; 1648 UINTN AttemptConfigOrderSize; 1649 UINTN TotalNumber; 1650 UINTN Index; 1651 1652 // 1653 // Is User creating a new attempt? 1654 // 1655 NewAttempt = FALSE; 1656 1657 if ((KeyValue >= KEY_MAC_ENTRY_BASE) && 1658 (KeyValue <= (UINT16) (mPrivate->MaxNic + KEY_MAC_ENTRY_BASE))) { 1659 // 1660 // User has pressed "Add an Attempt" and then selects a NIC. 1661 // 1662 NewAttempt = TRUE; 1663 } else if ((KeyValue >= KEY_ATTEMPT_ENTRY_BASE) && 1664 (KeyValue < (ISCSI_MAX_ATTEMPTS_NUM + KEY_ATTEMPT_ENTRY_BASE))) { 1665 1666 // 1667 // User has pressed "Attempt *". 1668 // 1669 NewAttempt = FALSE; 1670 } else { 1671 // 1672 // Don't process anything. 1673 // 1674 return EFI_SUCCESS; 1675 } 1676 1677 // 1678 // Free any attempt that is previously created but not saved to system. 1679 // 1680 if (mPrivate->NewAttempt != NULL) { 1681 FreePool (mPrivate->NewAttempt); 1682 mPrivate->NewAttempt = NULL; 1683 } 1684 1685 if (NewAttempt) { 1686 // 1687 // Determine which NIC user has selected for the new created attempt. 1688 // 1689 NicIndex = (UINT8) (KeyValue - KEY_MAC_ENTRY_BASE); 1690 NicInfo = IScsiGetNicInfoByIndex (NicIndex); 1691 if (NicInfo == NULL) { 1692 return EFI_NOT_FOUND; 1693 } 1694 1695 // 1696 // Create new attempt. 1697 // 1698 1699 AttemptConfigData = AllocateZeroPool (sizeof (ISCSI_ATTEMPT_CONFIG_NVDATA)); 1700 if (AttemptConfigData == NULL) { 1701 return EFI_OUT_OF_RESOURCES; 1702 } 1703 1704 ConfigData = &AttemptConfigData->SessionConfigData; 1705 ConfigData->TargetPort = ISCSI_WELL_KNOWN_PORT; 1706 ConfigData->ConnectTimeout = CONNECT_DEFAULT_TIMEOUT; 1707 ConfigData->ConnectRetryCount = CONNECT_MIN_RETRY; 1708 1709 AttemptConfigData->AuthenticationType = ISCSI_AUTH_TYPE_CHAP; 1710 AttemptConfigData->AuthConfigData.CHAP.CHAPType = ISCSI_CHAP_UNI; 1711 1712 // 1713 // Get current order number for this attempt. 1714 // 1715 AttemptConfigOrder = IScsiGetVariableAndSize ( 1716 L"AttemptOrder", 1717 &gIScsiConfigGuid, 1718 &AttemptConfigOrderSize 1719 ); 1720 1721 TotalNumber = AttemptConfigOrderSize / sizeof (UINT8); 1722 1723 if (AttemptConfigOrder == NULL) { 1724 CurrentAttemptConfigIndex = 1; 1725 } else { 1726 // 1727 // Get the max attempt config index. 1728 // 1729 CurrentAttemptConfigIndex = AttemptConfigOrder[0]; 1730 for (Index = 1; Index < TotalNumber; Index++) { 1731 if (CurrentAttemptConfigIndex < AttemptConfigOrder[Index]) { 1732 CurrentAttemptConfigIndex = AttemptConfigOrder[Index]; 1733 } 1734 } 1735 1736 CurrentAttemptConfigIndex++; 1737 } 1738 1739 TotalNumber++; 1740 1741 // 1742 // Record the mapping between attempt order and attempt's configdata. 1743 // 1744 AttemptConfigData->AttemptConfigIndex = CurrentAttemptConfigIndex; 1745 1746 if (AttemptConfigOrder != NULL) { 1747 FreePool (AttemptConfigOrder); 1748 } 1749 1750 // 1751 // Record the MAC info in Config Data. 1752 // 1753 IScsiMacAddrToStr ( 1754 &NicInfo->PermanentAddress, 1755 NicInfo->HwAddressSize, 1756 NicInfo->VlanId, 1757 MacString 1758 ); 1759 1760 UnicodeStrToAsciiStrS (MacString, AttemptConfigData->MacString, sizeof (AttemptConfigData->MacString)); 1761 AttemptConfigData->NicIndex = NicIndex; 1762 1763 // 1764 // Generate OUI-format ISID based on MAC address. 1765 // 1766 CopyMem (AttemptConfigData->SessionConfigData.IsId, &NicInfo->PermanentAddress, 6); 1767 AttemptConfigData->SessionConfigData.IsId[0] = 1768 (UINT8) (AttemptConfigData->SessionConfigData.IsId[0] & 0x3F); 1769 1770 // 1771 // Add the help info for the new attempt. 1772 // 1773 UnicodeSPrint ( 1774 mPrivate->PortString, 1775 (UINTN) ISCSI_NAME_IFR_MAX_SIZE, 1776 L"MAC: %s, PFA: Bus %d | Dev %d | Func %d", 1777 MacString, 1778 NicInfo->BusNumber, 1779 NicInfo->DeviceNumber, 1780 NicInfo->FunctionNumber 1781 ); 1782 1783 AttemptConfigData->AttemptTitleHelpToken = HiiSetString ( 1784 mCallbackInfo->RegisteredHandle, 1785 0, 1786 mPrivate->PortString, 1787 NULL 1788 ); 1789 if (AttemptConfigData->AttemptTitleHelpToken == 0) { 1790 FreePool (AttemptConfigData); 1791 return EFI_INVALID_PARAMETER; 1792 } 1793 1794 // 1795 // Set the attempt name to default. 1796 // 1797 UnicodeSPrint ( 1798 mPrivate->PortString, 1799 (UINTN) 128, 1800 L"%d", 1801 (UINTN) AttemptConfigData->AttemptConfigIndex 1802 ); 1803 UnicodeStrToAsciiStrS (mPrivate->PortString, AttemptConfigData->AttemptName, sizeof (AttemptConfigData->AttemptName)); 1804 1805 // 1806 // Save the created Attempt temporarily. If user does not save the attempt 1807 // by press 'KEY_SAVE_ATTEMPT_CONFIG' later, iSCSI driver would know that 1808 // and free resources. 1809 // 1810 mPrivate->NewAttempt = (VOID *) AttemptConfigData; 1811 1812 } else { 1813 // 1814 // Determine which Attempt user has selected to configure. 1815 // Get the attempt configuration data. 1816 // 1817 CurrentAttemptConfigIndex = (UINT8) (KeyValue - KEY_ATTEMPT_ENTRY_BASE); 1818 1819 AttemptConfigData = IScsiConfigGetAttemptByConfigIndex (CurrentAttemptConfigIndex); 1820 if (AttemptConfigData == NULL) { 1821 DEBUG ((DEBUG_ERROR, "Corresponding configuration data can not be retrieved!\n")); 1822 return EFI_NOT_FOUND; 1823 } 1824 } 1825 1826 // 1827 // Clear the old IFR data to avoid sharing it with other attempts. 1828 // 1829 if (IfrNvData->AuthenticationType == ISCSI_AUTH_TYPE_CHAP) { 1830 ZeroMem (IfrNvData->CHAPName, sizeof (IfrNvData->CHAPName)); 1831 ZeroMem (IfrNvData->CHAPSecret, sizeof (IfrNvData->CHAPSecret)); 1832 ZeroMem (IfrNvData->ReverseCHAPName, sizeof (IfrNvData->ReverseCHAPName)); 1833 ZeroMem (IfrNvData->ReverseCHAPSecret, sizeof (IfrNvData->ReverseCHAPSecret)); 1834 } 1835 1836 IScsiConvertAttemptConfigDataToIfrNvData (AttemptConfigData, IfrNvData); 1837 1838 // 1839 // Update current attempt to be a new created attempt or an existing attempt. 1840 // 1841 mCallbackInfo->Current = AttemptConfigData; 1842 1843 return EFI_SUCCESS; 1844 } 1845 1846 1847 /** 1848 1849 This function allows the caller to request the current 1850 configuration for one or more named elements. The resulting 1851 string is in <ConfigAltResp> format. Also, any and all alternative 1852 configuration strings shall be appended to the end of the 1853 current configuration string. If they are, they must appear 1854 after the current configuration. They must contain the same 1855 routing (GUID, NAME, PATH) as the current configuration string. 1856 They must have an additional description indicating the type of 1857 alternative configuration the string represents, 1858 "ALTCFG=<StringToken>". That <StringToken> (when 1859 converted from Hex UNICODE to binary) is a reference to a 1860 string in the associated string pack. 1861 1862 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 1863 1864 @param[in] Request A null-terminated Unicode string in 1865 <ConfigRequest> format. Note that this 1866 includes the routing information as well as 1867 the configurable name / value pairs. It is 1868 invalid for this string to be in 1869 <MultiConfigRequest> format. 1870 1871 @param[out] Progress On return, points to a character in the 1872 Request string. Points to the string's null 1873 terminator if request was successful. Points 1874 to the most recent "&" before the first 1875 failing name / value pair (or the beginning 1876 of the string if the failure is in the first 1877 name / value pair) if the request was not successful. 1878 1879 @param[out] Results A null-terminated Unicode string in 1880 <ConfigAltResp> format which has all values 1881 filled in for the names in the Request string. 1882 String to be allocated by the called function. 1883 1884 @retval EFI_SUCCESS The Results string is filled with the 1885 values corresponding to all requested 1886 names. 1887 1888 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the 1889 parts of the results that must be 1890 stored awaiting possible future 1891 protocols. 1892 1893 @retval EFI_INVALID_PARAMETER For example, passing in a NULL 1894 for the Request parameter 1895 would result in this type of 1896 error. In this case, the 1897 Progress parameter would be 1898 set to NULL. 1899 1900 @retval EFI_NOT_FOUND Routing data doesn't match any 1901 known driver. Progress set to the 1902 first character in the routing header. 1903 Note: There is no requirement that the 1904 driver validate the routing data. It 1905 must skip the <ConfigHdr> in order to 1906 process the names. 1907 1908 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set 1909 to most recent "&" before the 1910 error or the beginning of the 1911 string. 1912 1913 @retval EFI_INVALID_PARAMETER Unknown name. Progress points 1914 to the & before the name in 1915 question. 1916 1917 **/ 1918 EFI_STATUS 1919 EFIAPI 1920 IScsiFormExtractConfig ( 1921 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 1922 IN CONST EFI_STRING Request, 1923 OUT EFI_STRING *Progress, 1924 OUT EFI_STRING *Results 1925 ) 1926 { 1927 EFI_STATUS Status; 1928 CHAR8 *InitiatorName; 1929 UINTN BufferSize; 1930 ISCSI_CONFIG_IFR_NVDATA *IfrNvData; 1931 ISCSI_FORM_CALLBACK_INFO *Private; 1932 EFI_STRING ConfigRequestHdr; 1933 EFI_STRING ConfigRequest; 1934 BOOLEAN AllocatedRequest; 1935 UINTN Size; 1936 1937 if (This == NULL || Progress == NULL || Results == NULL) { 1938 return EFI_INVALID_PARAMETER; 1939 } 1940 1941 *Progress = Request; 1942 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIScsiConfigGuid, mVendorStorageName)) { 1943 return EFI_NOT_FOUND; 1944 } 1945 1946 ConfigRequestHdr = NULL; 1947 ConfigRequest = NULL; 1948 AllocatedRequest = FALSE; 1949 Size = 0; 1950 1951 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This); 1952 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA)); 1953 if (IfrNvData == NULL) { 1954 return EFI_OUT_OF_RESOURCES; 1955 } 1956 1957 if (Private->Current != NULL) { 1958 IScsiConvertAttemptConfigDataToIfrNvData (Private->Current, IfrNvData); 1959 } 1960 1961 BufferSize = ISCSI_NAME_MAX_SIZE; 1962 InitiatorName = (CHAR8 *) AllocateZeroPool (BufferSize); 1963 if (InitiatorName == NULL) { 1964 FreePool (IfrNvData); 1965 return EFI_OUT_OF_RESOURCES; 1966 } 1967 1968 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName); 1969 if (EFI_ERROR (Status)) { 1970 IfrNvData->InitiatorName[0] = L'\0'; 1971 } else { 1972 AsciiStrToUnicodeStrS ( 1973 InitiatorName, 1974 IfrNvData->InitiatorName, 1975 sizeof (IfrNvData->InitiatorName) / sizeof (IfrNvData->InitiatorName[0]) 1976 ); 1977 } 1978 1979 // 1980 // Convert buffer data to <ConfigResp> by helper function BlockToConfig(). 1981 // 1982 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA); 1983 ConfigRequest = Request; 1984 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { 1985 // 1986 // Request has no request element, construct full request string. 1987 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template 1988 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator 1989 // 1990 ConfigRequestHdr = HiiConstructConfigHdr (&gIScsiConfigGuid, mVendorStorageName, Private->DriverHandle); 1991 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); 1992 ConfigRequest = AllocateZeroPool (Size); 1993 if (ConfigRequest == NULL) { 1994 FreePool (IfrNvData); 1995 FreePool (InitiatorName); 1996 return EFI_OUT_OF_RESOURCES; 1997 } 1998 AllocatedRequest = TRUE; 1999 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); 2000 FreePool (ConfigRequestHdr); 2001 } 2002 2003 Status = gHiiConfigRouting->BlockToConfig ( 2004 gHiiConfigRouting, 2005 ConfigRequest, 2006 (UINT8 *) IfrNvData, 2007 BufferSize, 2008 Results, 2009 Progress 2010 ); 2011 FreePool (IfrNvData); 2012 FreePool (InitiatorName); 2013 2014 // 2015 // Free the allocated config request string. 2016 // 2017 if (AllocatedRequest) { 2018 FreePool (ConfigRequest); 2019 ConfigRequest = NULL; 2020 } 2021 // 2022 // Set Progress string to the original request string. 2023 // 2024 if (Request == NULL) { 2025 *Progress = NULL; 2026 } else if (StrStr (Request, L"OFFSET") == NULL) { 2027 *Progress = Request + StrLen (Request); 2028 } 2029 2030 return Status; 2031 } 2032 2033 2034 /** 2035 2036 This function applies changes in a driver's configuration. 2037 Input is a Configuration, which has the routing data for this 2038 driver followed by name / value configuration pairs. The driver 2039 must apply those pairs to its configurable storage. If the 2040 driver's configuration is stored in a linear block of data 2041 and the driver's name / value pairs are in <BlockConfig> 2042 format, it may use the ConfigToBlock helper function (above) to 2043 simplify the job. 2044 2045 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 2046 2047 @param[in] Configuration A null-terminated Unicode string in 2048 <ConfigString> format. 2049 2050 @param[out] Progress A pointer to a string filled in with the 2051 offset of the most recent '&' before the 2052 first failing name / value pair (or the 2053 beginning of the string if the failure 2054 is in the first name / value pair) or 2055 the terminating NULL if all was 2056 successful. 2057 2058 @retval EFI_SUCCESS The results have been distributed or are 2059 awaiting distribution. 2060 2061 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the 2062 parts of the results that must be 2063 stored awaiting possible future 2064 protocols. 2065 2066 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the 2067 Results parameter would result 2068 in this type of error. 2069 2070 @retval EFI_NOT_FOUND Target for the specified routing data 2071 was not found. 2072 2073 **/ 2074 EFI_STATUS 2075 EFIAPI 2076 IScsiFormRouteConfig ( 2077 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 2078 IN CONST EFI_STRING Configuration, 2079 OUT EFI_STRING *Progress 2080 ) 2081 { 2082 if (This == NULL || Configuration == NULL || Progress == NULL) { 2083 return EFI_INVALID_PARAMETER; 2084 } 2085 2086 // 2087 // Check routing data in <ConfigHdr>. 2088 // Note: if only one Storage is used, then this checking could be skipped. 2089 // 2090 if (!HiiIsConfigHdrMatch (Configuration, &gIScsiConfigGuid, mVendorStorageName)) { 2091 *Progress = Configuration; 2092 return EFI_NOT_FOUND; 2093 } 2094 2095 *Progress = Configuration + StrLen (Configuration); 2096 return EFI_SUCCESS; 2097 } 2098 2099 2100 /** 2101 2102 This function is called to provide results data to the driver. 2103 This data consists of a unique key that is used to identify 2104 which data is either being passed back or being asked for. 2105 2106 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. 2107 @param[in] Action Specifies the type of action taken by the browser. 2108 @param[in] QuestionId A unique value which is sent to the original 2109 exporting driver so that it can identify the type 2110 of data to expect. The format of the data tends to 2111 vary based on the opcode that generated the callback. 2112 @param[in] Type The type of value for the question. 2113 @param[in, out] Value A pointer to the data being sent to the original 2114 exporting driver. 2115 @param[out] ActionRequest On return, points to the action requested by the 2116 callback function. 2117 2118 @retval EFI_SUCCESS The callback successfully handled the action. 2119 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the 2120 variable and its data. 2121 @retval EFI_DEVICE_ERROR The variable could not be saved. 2122 @retval EFI_UNSUPPORTED The specified Action is not supported by the 2123 callback. 2124 **/ 2125 EFI_STATUS 2126 EFIAPI 2127 IScsiFormCallback ( 2128 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, 2129 IN EFI_BROWSER_ACTION Action, 2130 IN EFI_QUESTION_ID QuestionId, 2131 IN UINT8 Type, 2132 IN OUT EFI_IFR_TYPE_VALUE *Value, 2133 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest 2134 ) 2135 { 2136 ISCSI_FORM_CALLBACK_INFO *Private; 2137 UINTN BufferSize; 2138 CHAR8 *IScsiName; 2139 CHAR8 IpString[IP_STR_MAX_SIZE]; 2140 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN]; 2141 UINT64 Lun; 2142 EFI_IP_ADDRESS HostIp; 2143 EFI_IP_ADDRESS SubnetMask; 2144 EFI_IP_ADDRESS Gateway; 2145 ISCSI_CONFIG_IFR_NVDATA *IfrNvData; 2146 ISCSI_CONFIG_IFR_NVDATA OldIfrNvData; 2147 EFI_STATUS Status; 2148 CHAR16 AttemptName[ATTEMPT_NAME_SIZE + 4]; 2149 EFI_INPUT_KEY Key; 2150 2151 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) { 2152 // 2153 // Do nothing for UEFI OPEN/CLOSE Action 2154 // 2155 return EFI_SUCCESS; 2156 } 2157 2158 if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) { 2159 // 2160 // All other type return unsupported. 2161 // 2162 return EFI_UNSUPPORTED; 2163 } 2164 2165 if ((Value == NULL) || (ActionRequest == NULL)) { 2166 return EFI_INVALID_PARAMETER; 2167 } 2168 2169 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This); 2170 2171 // 2172 // Retrieve uncommitted data from Browser 2173 // 2174 2175 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA); 2176 IfrNvData = AllocateZeroPool (BufferSize); 2177 if (IfrNvData == NULL) { 2178 return EFI_OUT_OF_RESOURCES; 2179 } 2180 2181 IScsiName = (CHAR8 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE); 2182 if (IScsiName == NULL) { 2183 FreePool (IfrNvData); 2184 return EFI_OUT_OF_RESOURCES; 2185 } 2186 2187 Status = EFI_SUCCESS; 2188 2189 ZeroMem (&OldIfrNvData, BufferSize); 2190 2191 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData); 2192 2193 CopyMem (&OldIfrNvData, IfrNvData, BufferSize); 2194 2195 if (Action == EFI_BROWSER_ACTION_CHANGING) { 2196 switch (QuestionId) { 2197 case KEY_ADD_ATTEMPT: 2198 // 2199 // Check whether iSCSI initiator name is configured already. 2200 // 2201 mPrivate->InitiatorNameLength = ISCSI_NAME_MAX_SIZE; 2202 Status = gIScsiInitiatorName.Get ( 2203 &gIScsiInitiatorName, 2204 &mPrivate->InitiatorNameLength, 2205 mPrivate->InitiatorName 2206 ); 2207 if (EFI_ERROR (Status)) { 2208 CreatePopUp ( 2209 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2210 &Key, 2211 L"Error: please configure iSCSI initiator name first!", 2212 NULL 2213 ); 2214 break; 2215 } 2216 2217 Status = IScsiConfigAddAttempt (); 2218 break; 2219 2220 case KEY_DELETE_ATTEMPT: 2221 CopyMem ( 2222 OldIfrNvData.DeleteAttemptList, 2223 IfrNvData->DeleteAttemptList, 2224 sizeof (IfrNvData->DeleteAttemptList) 2225 ); 2226 Status = IScsiConfigDisplayDeleteAttempts (IfrNvData); 2227 break; 2228 2229 case KEY_ORDER_ATTEMPT_CONFIG: 2230 // 2231 // Order the attempt according to user input. 2232 // 2233 CopyMem ( 2234 OldIfrNvData.DynamicOrderedList, 2235 IfrNvData->DynamicOrderedList, 2236 sizeof (IfrNvData->DynamicOrderedList) 2237 ); 2238 IScsiConfigDisplayOrderAttempts (); 2239 break; 2240 2241 default: 2242 Status = IScsiConfigProcessDefault (QuestionId, IfrNvData); 2243 break; 2244 } 2245 } else if (Action == EFI_BROWSER_ACTION_CHANGED) { 2246 switch (QuestionId) { 2247 case KEY_INITIATOR_NAME: 2248 UnicodeStrToAsciiStrS (IfrNvData->InitiatorName, IScsiName, ISCSI_NAME_MAX_SIZE); 2249 BufferSize = AsciiStrSize (IScsiName); 2250 2251 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName); 2252 if (EFI_ERROR (Status)) { 2253 CreatePopUp ( 2254 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2255 &Key, 2256 L"Invalid iSCSI Name!", 2257 NULL 2258 ); 2259 } 2260 2261 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; 2262 break; 2263 case KEY_ATTEMPT_NAME: 2264 if (StrLen (IfrNvData->AttemptName) > ATTEMPT_NAME_SIZE) { 2265 CopyMem (AttemptName, IfrNvData->AttemptName, ATTEMPT_NAME_SIZE * sizeof (CHAR16)); 2266 CopyMem (&AttemptName[ATTEMPT_NAME_SIZE], L"...", 4 * sizeof (CHAR16)); 2267 } else { 2268 CopyMem ( 2269 AttemptName, 2270 IfrNvData->AttemptName, 2271 (StrLen (IfrNvData->AttemptName) + 1) * sizeof (CHAR16) 2272 ); 2273 } 2274 2275 UnicodeStrToAsciiStrS (IfrNvData->AttemptName, Private->Current->AttemptName, sizeof (Private->Current->AttemptName)); 2276 2277 IScsiConfigUpdateAttempt (); 2278 2279 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; 2280 break; 2281 2282 case KEY_SAVE_ATTEMPT_CONFIG: 2283 Status = IScsiConvertIfrNvDataToAttemptConfigData (IfrNvData, Private->Current); 2284 if (EFI_ERROR (Status)) { 2285 break; 2286 } 2287 2288 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; 2289 break; 2290 2291 case KEY_SAVE_ORDER_CHANGES: 2292 // 2293 // Sync the Attempt Order to NVR. 2294 // 2295 Status = IScsiConfigOrderAttempts (IfrNvData); 2296 if (EFI_ERROR (Status)) { 2297 break; 2298 } 2299 2300 IScsiConfigUpdateAttempt (); 2301 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; 2302 break; 2303 2304 case KEY_IGNORE_ORDER_CHANGES: 2305 CopyMem ( 2306 IfrNvData->DynamicOrderedList, 2307 OldIfrNvData.DynamicOrderedList, 2308 sizeof (IfrNvData->DynamicOrderedList) 2309 ); 2310 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; 2311 break; 2312 2313 case KEY_SAVE_DELETE_ATTEMPT: 2314 // 2315 // Delete the Attempt Order from NVR 2316 // 2317 Status = IScsiConfigDeleteAttempts (IfrNvData); 2318 if (EFI_ERROR (Status)) { 2319 break; 2320 } 2321 2322 IScsiConfigUpdateAttempt (); 2323 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT; 2324 break; 2325 2326 case KEY_IGNORE_DELETE_ATTEMPT: 2327 CopyMem ( 2328 IfrNvData->DeleteAttemptList, 2329 OldIfrNvData.DeleteAttemptList, 2330 sizeof (IfrNvData->DeleteAttemptList) 2331 ); 2332 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT; 2333 break; 2334 2335 case KEY_IP_MODE: 2336 switch (Value->u8) { 2337 case IP_MODE_IP6: 2338 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp)); 2339 IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, TRUE, IfrNvData->TargetIp); 2340 Private->Current->AutoConfigureMode = 0; 2341 break; 2342 2343 case IP_MODE_IP4: 2344 ZeroMem (IfrNvData->TargetIp, sizeof (IfrNvData->TargetIp)); 2345 IScsiIpToStr (&Private->Current->SessionConfigData.TargetIp, FALSE, IfrNvData->TargetIp); 2346 Private->Current->AutoConfigureMode = 0; 2347 2348 break; 2349 } 2350 2351 break; 2352 2353 case KEY_LOCAL_IP: 2354 Status = NetLibStrToIp4 (IfrNvData->LocalIp, &HostIp.v4); 2355 if (EFI_ERROR (Status) || 2356 ((Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) && 2357 !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) { 2358 CreatePopUp ( 2359 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2360 &Key, 2361 L"Invalid IP address!", 2362 NULL 2363 ); 2364 2365 Status = EFI_INVALID_PARAMETER; 2366 } else { 2367 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4)); 2368 } 2369 2370 break; 2371 2372 case KEY_SUBNET_MASK: 2373 Status = NetLibStrToIp4 (IfrNvData->SubnetMask, &SubnetMask.v4); 2374 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) { 2375 CreatePopUp ( 2376 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2377 &Key, 2378 L"Invalid Subnet Mask!", 2379 NULL 2380 ); 2381 2382 Status = EFI_INVALID_PARAMETER; 2383 } else { 2384 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4)); 2385 } 2386 2387 break; 2388 2389 case KEY_GATE_WAY: 2390 Status = NetLibStrToIp4 (IfrNvData->Gateway, &Gateway.v4); 2391 if (EFI_ERROR (Status) || 2392 ((Gateway.Addr[0] != 0) && 2393 (Private->Current->SessionConfigData.SubnetMask.Addr[0] != 0) && 2394 !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL(*(UINT32*)Private->Current->SessionConfigData.SubnetMask.Addr)))) { 2395 CreatePopUp ( 2396 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2397 &Key, 2398 L"Invalid Gateway!", 2399 NULL 2400 ); 2401 Status = EFI_INVALID_PARAMETER; 2402 } else { 2403 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4)); 2404 } 2405 2406 break; 2407 2408 case KEY_TARGET_IP: 2409 UnicodeStrToAsciiStrS (IfrNvData->TargetIp, IpString, sizeof (IpString)); 2410 Status = IScsiAsciiStrToIp (IpString, IfrNvData->IpMode, &HostIp); 2411 if (EFI_ERROR (Status) || IP4_IS_LOCAL_BROADCAST (EFI_NTOHL(HostIp.v4)) || IP4_IS_UNSPECIFIED (EFI_NTOHL(HostIp.v4))) { 2412 CreatePopUp ( 2413 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2414 &Key, 2415 L"Invalid IP address!", 2416 NULL 2417 ); 2418 Status = EFI_INVALID_PARAMETER; 2419 } else { 2420 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp, sizeof (HostIp)); 2421 } 2422 2423 break; 2424 2425 case KEY_TARGET_NAME: 2426 UnicodeStrToAsciiStrS (IfrNvData->TargetName, IScsiName, ISCSI_NAME_MAX_SIZE); 2427 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName)); 2428 if (EFI_ERROR (Status)) { 2429 CreatePopUp ( 2430 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2431 &Key, 2432 L"Invalid iSCSI Name!", 2433 NULL 2434 ); 2435 } else { 2436 AsciiStrCpyS (Private->Current->SessionConfigData.TargetName, ISCSI_NAME_MAX_SIZE, IScsiName); 2437 } 2438 2439 break; 2440 2441 case KEY_DHCP_ENABLE: 2442 if (IfrNvData->InitiatorInfoFromDhcp == 0) { 2443 IfrNvData->TargetInfoFromDhcp = 0; 2444 } 2445 2446 break; 2447 2448 case KEY_BOOT_LUN: 2449 UnicodeStrToAsciiStrS (IfrNvData->BootLun, LunString, sizeof (LunString)); 2450 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun); 2451 if (EFI_ERROR (Status)) { 2452 CreatePopUp ( 2453 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 2454 &Key, 2455 L"Invalid LUN string!", 2456 NULL 2457 ); 2458 } else { 2459 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun)); 2460 } 2461 2462 break; 2463 2464 case KEY_AUTH_TYPE: 2465 switch (Value->u8) { 2466 case ISCSI_AUTH_TYPE_CHAP: 2467 IfrNvData->CHAPType = ISCSI_CHAP_UNI; 2468 break; 2469 default: 2470 break; 2471 } 2472 2473 break; 2474 2475 case KEY_CHAP_NAME: 2476 UnicodeStrToAsciiStrS ( 2477 IfrNvData->CHAPName, 2478 Private->Current->AuthConfigData.CHAP.CHAPName, 2479 sizeof (Private->Current->AuthConfigData.CHAP.CHAPName) 2480 ); 2481 break; 2482 2483 case KEY_CHAP_SECRET: 2484 UnicodeStrToAsciiStrS ( 2485 IfrNvData->CHAPSecret, 2486 Private->Current->AuthConfigData.CHAP.CHAPSecret, 2487 sizeof (Private->Current->AuthConfigData.CHAP.CHAPSecret) 2488 ); 2489 break; 2490 2491 case KEY_REVERSE_CHAP_NAME: 2492 UnicodeStrToAsciiStrS ( 2493 IfrNvData->ReverseCHAPName, 2494 Private->Current->AuthConfigData.CHAP.ReverseCHAPName, 2495 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPName) 2496 ); 2497 break; 2498 2499 case KEY_REVERSE_CHAP_SECRET: 2500 UnicodeStrToAsciiStrS ( 2501 IfrNvData->ReverseCHAPSecret, 2502 Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret, 2503 sizeof (Private->Current->AuthConfigData.CHAP.ReverseCHAPSecret) 2504 ); 2505 break; 2506 2507 case KEY_CONFIG_ISID: 2508 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId); 2509 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId); 2510 2511 break; 2512 2513 default: 2514 break; 2515 } 2516 } 2517 2518 if (!EFI_ERROR (Status)) { 2519 // 2520 // Pass changed uncommitted data back to Form Browser. 2521 // 2522 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA); 2523 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL); 2524 } 2525 2526 FreePool (IfrNvData); 2527 FreePool (IScsiName); 2528 2529 return Status; 2530 } 2531 2532 2533 /** 2534 Initialize the iSCSI configuration form. 2535 2536 @param[in] DriverBindingHandle The iSCSI driverbinding handle. 2537 2538 @retval EFI_SUCCESS The iSCSI configuration form is initialized. 2539 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. 2540 2541 **/ 2542 EFI_STATUS 2543 IScsiConfigFormInit ( 2544 IN EFI_HANDLE DriverBindingHandle 2545 ) 2546 { 2547 EFI_STATUS Status; 2548 ISCSI_FORM_CALLBACK_INFO *CallbackInfo; 2549 2550 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO)); 2551 if (CallbackInfo == NULL) { 2552 return EFI_OUT_OF_RESOURCES; 2553 } 2554 2555 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE; 2556 CallbackInfo->Current = NULL; 2557 2558 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig; 2559 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig; 2560 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback; 2561 2562 // 2563 // Install Device Path Protocol and Config Access protocol to driver handle. 2564 // 2565 Status = gBS->InstallMultipleProtocolInterfaces ( 2566 &CallbackInfo->DriverHandle, 2567 &gEfiDevicePathProtocolGuid, 2568 &mIScsiHiiVendorDevicePath, 2569 &gEfiHiiConfigAccessProtocolGuid, 2570 &CallbackInfo->ConfigAccess, 2571 NULL 2572 ); 2573 ASSERT_EFI_ERROR (Status); 2574 2575 // 2576 // Publish our HII data. 2577 // 2578 CallbackInfo->RegisteredHandle = HiiAddPackages ( 2579 &gIScsiConfigGuid, 2580 CallbackInfo->DriverHandle, 2581 IScsiDxeStrings, 2582 IScsiConfigVfrBin, 2583 NULL 2584 ); 2585 if (CallbackInfo->RegisteredHandle == NULL) { 2586 gBS->UninstallMultipleProtocolInterfaces ( 2587 &CallbackInfo->DriverHandle, 2588 &gEfiDevicePathProtocolGuid, 2589 &mIScsiHiiVendorDevicePath, 2590 &gEfiHiiConfigAccessProtocolGuid, 2591 &CallbackInfo->ConfigAccess, 2592 NULL 2593 ); 2594 FreePool(CallbackInfo); 2595 return EFI_OUT_OF_RESOURCES; 2596 } 2597 2598 mCallbackInfo = CallbackInfo; 2599 2600 return EFI_SUCCESS; 2601 } 2602 2603 2604 /** 2605 Unload the iSCSI configuration form, this includes: delete all the iSCSI 2606 configuration entries, uninstall the form callback protocol, and 2607 free the resources used. 2608 2609 @param[in] DriverBindingHandle The iSCSI driverbinding handle. 2610 2611 @retval EFI_SUCCESS The iSCSI configuration form is unloaded. 2612 @retval Others Failed to unload the form. 2613 2614 **/ 2615 EFI_STATUS 2616 IScsiConfigFormUnload ( 2617 IN EFI_HANDLE DriverBindingHandle 2618 ) 2619 { 2620 ISCSI_ATTEMPT_CONFIG_NVDATA *AttemptConfigData; 2621 ISCSI_NIC_INFO *NicInfo; 2622 LIST_ENTRY *Entry; 2623 EFI_STATUS Status; 2624 2625 while (!IsListEmpty (&mPrivate->AttemptConfigs)) { 2626 Entry = NetListRemoveHead (&mPrivate->AttemptConfigs); 2627 AttemptConfigData = NET_LIST_USER_STRUCT (Entry, ISCSI_ATTEMPT_CONFIG_NVDATA, Link); 2628 FreePool (AttemptConfigData); 2629 mPrivate->AttemptCount--; 2630 } 2631 2632 ASSERT (mPrivate->AttemptCount == 0); 2633 2634 while (!IsListEmpty (&mPrivate->NicInfoList)) { 2635 Entry = NetListRemoveHead (&mPrivate->NicInfoList); 2636 NicInfo = NET_LIST_USER_STRUCT (Entry, ISCSI_NIC_INFO, Link); 2637 FreePool (NicInfo); 2638 mPrivate->NicCount--; 2639 } 2640 2641 ASSERT (mPrivate->NicCount == 0); 2642 2643 // 2644 // Free attempt is created but not saved to system. 2645 // 2646 if (mPrivate->NewAttempt != NULL) { 2647 FreePool (mPrivate->NewAttempt); 2648 } 2649 2650 FreePool (mPrivate); 2651 mPrivate = NULL; 2652 2653 // 2654 // Remove HII package list. 2655 // 2656 HiiRemovePackages (mCallbackInfo->RegisteredHandle); 2657 2658 // 2659 // Uninstall Device Path Protocol and Config Access protocol. 2660 // 2661 Status = gBS->UninstallMultipleProtocolInterfaces ( 2662 mCallbackInfo->DriverHandle, 2663 &gEfiDevicePathProtocolGuid, 2664 &mIScsiHiiVendorDevicePath, 2665 &gEfiHiiConfigAccessProtocolGuid, 2666 &mCallbackInfo->ConfigAccess, 2667 NULL 2668 ); 2669 2670 FreePool (mCallbackInfo); 2671 2672 return Status; 2673 } 2674