2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2011, 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
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.
15 #include "IScsiImpl.h"
17 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
18 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
19 UINTN mNumberOfIScsiDevices
= 0;
20 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
22 LIST_ENTRY mIScsiConfigFormList
= {
23 &mIScsiConfigFormList
,
27 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
33 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
34 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
41 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
43 (UINT8
) (END_DEVICE_PATH_LENGTH
),
44 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
50 Convert the IPv4 address into a dotted string.
52 @param[in] Ip The IPv4 address.
53 @param[out] Str The dotted IP string.
57 IN EFI_IPv4_ADDRESS
*Ip
,
61 UnicodeSPrint ( Str
, 2 * IP4_STR_MAX_SIZE
, L
"%d.%d.%d.%d", Ip
->Addr
[0], Ip
->Addr
[1], Ip
->Addr
[2], Ip
->Addr
[3]);
66 Parse IsId in string format and convert it to binary.
68 @param[in] String The buffer of the string to be parsed.
69 @param[in, out] IsId The buffer to store IsId.
71 @retval EFI_SUCCESS The operation finished successfully.
72 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
76 IScsiParseIsIdFromString (
77 IN CONST CHAR16
*String
,
85 CHAR16 PortString
[ISCSI_NAME_IFR_MAX_SIZE
];
88 if ((String
== NULL
) || (IsId
== NULL
)) {
89 return EFI_INVALID_PARAMETER
;
92 IsIdStr
= (CHAR16
*) String
;
94 if (StrLen (IsIdStr
) != 6) {
97 (UINTN
) ISCSI_NAME_IFR_MAX_SIZE
,
98 L
"Error! Input is incorrect, please input 6 hex numbers!\n"
102 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
108 return EFI_INVALID_PARAMETER
;
111 for (Index
= 3; Index
< 6; Index
++) {
112 CopyMem (TempStr
, IsIdStr
, sizeof (TempStr
));
116 // Convert the string to IsId. StrHexToUintn stops at the first character
117 // that is not a valid hex character, '\0' here.
119 NodeVal
= StrHexToUintn (TempStr
);
121 IsId
[Index
] = (UINT8
) NodeVal
;
123 IsIdStr
= IsIdStr
+ 2;
130 Convert IsId from binary to string format.
132 @param[out] String The buffer to store the converted string.
133 @param[in] IsId The buffer to store IsId.
135 @retval EFI_SUCCESS The string converted successfully.
136 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
140 IScsiConvertIsIdToString (
148 if ((String
== NULL
) || (IsId
== NULL
)) {
149 return EFI_INVALID_PARAMETER
;
152 for (Index
= 0; Index
< 6; Index
++) {
153 if (IsId
[Index
] <= 0xF) {
154 Number
= UnicodeSPrint (
156 2 * ISID_CONFIGURABLE_STORAGE
,
161 Number
= UnicodeSPrint (
163 2 * ISID_CONFIGURABLE_STORAGE
,
170 String
= String
+ Number
;
180 Update the list of iSCSI devices the iSCSI driver is controlling.
182 @retval EFI_SUCCESS The callback successfully handled the action.
183 @retval Others Other errors as indicated.
186 IScsiUpdateDeviceList (
191 ISCSI_DEVICE_LIST
*DeviceList
;
197 UINTN LastDeviceIndex
;
198 EFI_MAC_ADDRESS MacAddress
;
201 ISCSI_MAC_INFO
*CurMacInfo
;
202 ISCSI_MAC_INFO TempMacInfo
;
203 CHAR16 MacString
[70];
204 UINTN DeviceListSize
;
207 // Dump all the handles the Managed Network Service Binding Protocol is installed on.
209 Status
= gBS
->LocateHandleBuffer (
211 &gEfiManagedNetworkServiceBindingProtocolGuid
,
216 if (EFI_ERROR (Status
)) {
221 Status
= gRT
->GetVariable (
223 &gIp4IScsiConfigGuid
,
228 if (Status
== EFI_BUFFER_TOO_SMALL
) {
229 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DataSize
);
233 &gIp4IScsiConfigGuid
,
241 for (HandleIndex
= 0; HandleIndex
< NumHandles
; HandleIndex
++) {
242 Status
= NetLibGetMacAddress (Handles
[HandleIndex
], &MacAddress
, &HwAddressSize
);
243 ASSERT (Status
== EFI_SUCCESS
);
244 VlanId
= NetLibGetVlanId (Handles
[HandleIndex
]);
246 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
247 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
248 if ((CurMacInfo
->Len
== HwAddressSize
) &&
249 (CurMacInfo
->VlanId
== VlanId
) &&
250 (NET_MAC_EQUAL (&CurMacInfo
->Mac
, MacAddress
.Addr
, HwAddressSize
))
253 // The previous configured NIC is still here.
255 if (Index
!= LastDeviceIndex
) {
257 // Swap the current MAC address entry with the one indexed by
260 CopyMem (&TempMacInfo
, CurMacInfo
, sizeof (ISCSI_MAC_INFO
));
261 CopyMem (CurMacInfo
, &DeviceList
->MacInfo
[LastDeviceIndex
], sizeof (ISCSI_MAC_INFO
));
262 CopyMem (&DeviceList
->MacInfo
[LastDeviceIndex
], &TempMacInfo
, sizeof (ISCSI_MAC_INFO
));
269 if (LastDeviceIndex
== DeviceList
->NumDevice
) {
274 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
276 // delete the variables
278 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
279 IScsiMacAddrToStr (&CurMacInfo
->Mac
, CurMacInfo
->Len
, CurMacInfo
->VlanId
, MacString
);
280 gRT
->SetVariable (MacString
, &gEfiIScsiInitiatorNameProtocolGuid
, 0, 0, NULL
);
281 gRT
->SetVariable (MacString
, &gIScsiCHAPAuthInfoGuid
, 0, 0, NULL
);
284 FreePool (DeviceList
);
285 } else if (Status
!= EFI_NOT_FOUND
) {
290 // Construct the new iSCSI device list.
292 DeviceListSize
= sizeof (ISCSI_DEVICE_LIST
) + (NumHandles
- 1) * sizeof (ISCSI_MAC_INFO
);
293 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DeviceListSize
);
294 DeviceList
->NumDevice
= (UINT8
) NumHandles
;
296 for (Index
= 0; Index
< NumHandles
; Index
++) {
297 NetLibGetMacAddress (Handles
[Index
], &MacAddress
, &HwAddressSize
);
299 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
300 CopyMem (&CurMacInfo
->Mac
, MacAddress
.Addr
, HwAddressSize
);
301 CurMacInfo
->Len
= (UINT8
) HwAddressSize
;
302 CurMacInfo
->VlanId
= NetLibGetVlanId (Handles
[Index
]);
307 &gIp4IScsiConfigGuid
,
308 ISCSI_CONFIG_VAR_ATTR
,
313 FreePool (DeviceList
);
320 Get the iSCSI configuration form entry by the index of the goto opcode actived.
322 @param[in] Index The 0-based index of the goto opcode actived.
324 @return The iSCSI configuration form entry found.
326 ISCSI_CONFIG_FORM_ENTRY
*
327 IScsiGetConfigFormEntryByIndex (
333 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
336 ConfigFormEntry
= NULL
;
338 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
339 if (CurrentIndex
== Index
) {
340 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
347 return ConfigFormEntry
;
351 Convert the iSCSI configuration data into the IFR data.
353 @param[in] ConfigFormEntry The iSCSI configuration form entry.
354 @param[out] IfrNvData The IFR nv data.
358 IScsiConvertDeviceConfigDataToIfrNvData (
359 IN ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
360 OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
363 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
364 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
367 // Normal session configuration parameters.
369 SessionConfigData
= &ConfigFormEntry
->SessionConfigData
;
370 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
372 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
373 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
374 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
376 IScsiIpToStr (&SessionConfigData
->LocalIp
, IfrNvData
->LocalIp
);
377 IScsiIpToStr (&SessionConfigData
->SubnetMask
, IfrNvData
->SubnetMask
);
378 IScsiIpToStr (&SessionConfigData
->Gateway
, IfrNvData
->Gateway
);
379 IScsiIpToStr (&SessionConfigData
->TargetIp
, IfrNvData
->TargetIp
);
381 IScsiAsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
383 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
385 IScsiConvertIsIdToString (IfrNvData
->IsId
, SessionConfigData
->IsId
);
388 // CHAP authentication parameters.
390 AuthConfigData
= &ConfigFormEntry
->AuthConfigData
;
392 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
394 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
395 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
396 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
397 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
401 This function allows the caller to request the current
402 configuration for one or more named elements. The resulting
403 string is in <ConfigAltResp> format. Any and all alternative
404 configuration strings shall also be appended to the end of the
405 current configuration string. If they are, they must appear
406 after the current configuration. They must contain the same
407 routing (GUID, NAME, PATH) as the current configuration string.
408 They must have an additional description indicating the type of
409 alternative configuration the string represents,
410 "ALTCFG=<StringToken>". That <StringToken> (when
411 converted from Hex UNICODE to binary) is a reference to a
412 string in the associated string pack.
414 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
415 @param[in] Request A null-terminated Unicode string in
416 <ConfigRequest> format. Note that this
417 includes the routing information as well as
418 the configurable name / value pairs. It is
419 invalid for this string to be in
420 <MultiConfigRequest> format.
421 @param[out] Progress On return, points to a character in the
422 Request string. Points to the string's null
423 terminator if request was successful. Points
424 to the most recent "&" before the first
425 failing name / value pair (or the beginning
426 of the string if the failure is in the first
427 name / value pair) if the request was not
429 @param[out] Results A null-terminated Unicode string in
430 <ConfigAltResp> format which has all values
431 filled in for the names in the Request string.
432 String to be allocated by the called function.
434 @retval EFI_SUCCESS The Results string is filled with the
435 values corresponding to all requested
437 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
438 parts of the results that must be
439 stored awaiting possible future
441 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
442 for the Request parameter
443 would result in this type of
444 error. In this case, the
445 Progress parameter would be
447 @retval EFI_NOT_FOUND Routing data doesn't match any
448 known driver. Progress set to the
449 first character in the routing header.
450 Note: There is no requirement that the
451 driver validate the routing data. It
452 must skip the <ConfigHdr> in order to
454 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
455 to most recent & before the
456 error or the beginning of the
458 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
459 to the & before the name in
460 question.Currently not implemented.
464 IScsiFormExtractConfig (
465 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
466 IN CONST EFI_STRING Request
,
467 OUT EFI_STRING
*Progress
,
468 OUT EFI_STRING
*Results
472 CHAR8 InitiatorName
[ISCSI_NAME_MAX_SIZE
];
474 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
475 ISCSI_FORM_CALLBACK_INFO
*Private
;
476 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
477 EFI_STRING ConfigRequestHdr
;
478 EFI_STRING ConfigRequest
;
479 BOOLEAN AllocatedRequest
;
482 if (Progress
== NULL
|| Results
== NULL
) {
483 return EFI_INVALID_PARAMETER
;
487 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gIp4IScsiConfigGuid
, mVendorStorageName
)) {
488 return EFI_NOT_FOUND
;
491 ConfigRequestHdr
= NULL
;
492 ConfigRequest
= NULL
;
493 AllocatedRequest
= FALSE
;
496 if (!mIScsiDeviceListUpdated
) {
498 // Update the device list.
500 IScsiUpdateDeviceList ();
501 mIScsiDeviceListUpdated
= TRUE
;
504 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
505 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
506 ASSERT (IfrNvData
!= NULL
);
507 if (Private
->Current
!= NULL
) {
508 IScsiConvertDeviceConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
511 BufferSize
= ISCSI_NAME_MAX_SIZE
;
512 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
513 if (EFI_ERROR (Status
)) {
514 IfrNvData
->InitiatorName
[0] = L
'\0';
516 IScsiAsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
520 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
522 HiiConfigRouting
= Private
->ConfigRouting
;
523 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
524 ConfigRequest
= Request
;
525 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
527 // Request has no request element, construct full request string.
528 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
529 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
531 ConfigRequestHdr
= HiiConstructConfigHdr (&gIp4IScsiConfigGuid
, mVendorStorageName
, Private
->DriverHandle
);
532 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
533 ConfigRequest
= AllocateZeroPool (Size
);
534 ASSERT (ConfigRequest
!= NULL
);
535 AllocatedRequest
= TRUE
;
536 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
537 FreePool (ConfigRequestHdr
);
539 Status
= HiiConfigRouting
->BlockToConfig (
547 FreePool (IfrNvData
);
549 // Free the allocated config request string.
551 if (AllocatedRequest
) {
552 FreePool (ConfigRequest
);
553 ConfigRequest
= NULL
;
557 // Set Progress string to the original request string.
559 if (Request
== NULL
) {
561 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
562 *Progress
= Request
+ StrLen (Request
);
569 This function applies changes in a driver's configuration.
570 Input is a Configuration, which has the routing data for this
571 driver followed by name / value configuration pairs. The driver
572 must apply those pairs to its configurable storage. If the
573 driver's configuration is stored in a linear block of data
574 and the driver's name / value pairs are in <BlockConfig>
575 format, it may use the ConfigToBlock helper function (above) to
576 simplify the job. Currently not implemented.
578 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
579 @param[in] Configuration A null-terminated Unicode string in
580 <ConfigString> format.
581 @param[out] Progress A pointer to a string filled in with the
582 offset of the most recent '&' before the
583 first failing name / value pair (or the
584 beginn ing of the string if the failure
585 is in the first name / value pair) or
586 the terminating NULL if all was
589 @retval EFI_SUCCESS The results have been distributed or are
590 awaiting distribution.
591 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
592 parts of the results that must be
593 stored awaiting possible future
595 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
596 Results parameter would result
597 in this type of error.
598 @retval EFI_NOT_FOUND Target for the specified routing data
603 IScsiFormRouteConfig (
604 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
605 IN CONST EFI_STRING Configuration
,
606 OUT EFI_STRING
*Progress
609 if (Configuration
== NULL
|| Progress
== NULL
) {
610 return EFI_INVALID_PARAMETER
;
614 // Check routing data in <ConfigHdr>.
615 // Note: if only one Storage is used, then this checking could be skipped.
617 if (!HiiIsConfigHdrMatch (Configuration
, &gIp4IScsiConfigGuid
, mVendorStorageName
)) {
618 *Progress
= Configuration
;
619 return EFI_NOT_FOUND
;
622 *Progress
= Configuration
+ StrLen (Configuration
);
627 This function is called to provide results data to the driver.
628 This data consists of a unique key that is used to identify
629 which data is either being passed back or being asked for.
631 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
632 @param[in] Action Specifies the type of action taken by the browser.
633 @param[in] QuestionId A unique value which is sent to the original
634 exporting driver so that it can identify the type
635 of data to expect. The format of the data tends to
636 vary based on the opcode that enerated the callback.
637 @param[in] Type The type of value for the question.
638 @param[in] Value A pointer to the data being sent to the original
640 @param[out] ActionRequest On return, points to the action requested by the
643 @retval EFI_SUCCESS The callback successfully handled the action.
644 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
645 variable and its data.
646 @retval EFI_DEVICE_ERROR The variable could not be saved.
647 @retval EFI_UNSUPPORTED The specified Action is not supported by the
648 callback.Currently not implemented.
649 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
650 @retval Others Other errors as indicated.
655 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
656 IN EFI_BROWSER_ACTION Action
,
657 IN EFI_QUESTION_ID QuestionId
,
659 IN EFI_IFR_TYPE_VALUE
*Value
,
660 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
663 ISCSI_FORM_CALLBACK_INFO
*Private
;
665 CHAR8 IScsiName
[ISCSI_NAME_MAX_SIZE
];
666 CHAR16 PortString
[128];
667 CHAR8 Ip4String
[IP4_STR_MAX_SIZE
];
668 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
670 EFI_STRING_ID DeviceFormTitleToken
;
671 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
672 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
673 EFI_IP_ADDRESS HostIp
;
674 EFI_IP_ADDRESS SubnetMask
;
675 EFI_IP_ADDRESS Gateway
;
679 if (Action
!= EFI_BROWSER_ACTION_CHANGING
&& Action
!= EFI_BROWSER_ACTION_CHANGED
) {
680 return EFI_UNSUPPORTED
;
683 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
685 // Retrive uncommitted data from Browser
687 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
688 ASSERT (IfrNvData
!= NULL
);
689 if (!HiiGetBrowserData (&gIp4IScsiConfigGuid
, mVendorStorageName
, sizeof (ISCSI_CONFIG_IFR_NVDATA
), (UINT8
*) IfrNvData
)) {
690 FreePool (IfrNvData
);
691 return EFI_NOT_FOUND
;
693 Status
= EFI_SUCCESS
;
695 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
696 if ((QuestionId
>= KEY_DEVICE_ENTRY_BASE
) && (QuestionId
< (mNumberOfIScsiDevices
+ KEY_DEVICE_ENTRY_BASE
))) {
698 // In case goto the device configuration form, update the device form title.
700 ConfigFormEntry
= IScsiGetConfigFormEntryByIndex ((UINT32
) (QuestionId
- KEY_DEVICE_ENTRY_BASE
));
701 ASSERT (ConfigFormEntry
!= NULL
);
703 UnicodeSPrint (PortString
, (UINTN
) 128, L
"Port %s", ConfigFormEntry
->MacString
);
704 DeviceFormTitleToken
= (EFI_STRING_ID
) STR_ISCSI_DEVICE_FORM_TITLE
;
705 HiiSetString (Private
->RegisteredHandle
, DeviceFormTitleToken
, PortString
, NULL
);
707 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry
, IfrNvData
);
709 Private
->Current
= ConfigFormEntry
;
711 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
712 switch (QuestionId
) {
713 case KEY_INITIATOR_NAME
:
714 IScsiUnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
715 BufferSize
= AsciiStrSize (IScsiName
);
717 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
718 if (EFI_ERROR (Status
)) {
719 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid iSCSI Name!", NULL
);
725 IScsiUnicodeStrToAsciiStr (IfrNvData
->LocalIp
, Ip4String
);
726 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
727 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
728 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid IP address!", NULL
);
729 Status
= EFI_INVALID_PARAMETER
;
731 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
736 case KEY_SUBNET_MASK
:
737 IScsiUnicodeStrToAsciiStr (IfrNvData
->SubnetMask
, Ip4String
);
738 Status
= IScsiAsciiStrToIp (Ip4String
, &SubnetMask
.v4
);
739 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
740 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid Subnet Mask!", NULL
);
741 Status
= EFI_INVALID_PARAMETER
;
743 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
749 IScsiUnicodeStrToAsciiStr (IfrNvData
->Gateway
, Ip4String
);
750 Status
= IScsiAsciiStrToIp (Ip4String
, &Gateway
.v4
);
751 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
752 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid Gateway!", NULL
);
753 Status
= EFI_INVALID_PARAMETER
;
755 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
761 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetIp
, Ip4String
);
762 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
763 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
764 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid IP address!", NULL
);
765 Status
= EFI_INVALID_PARAMETER
;
767 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
772 case KEY_TARGET_NAME
:
773 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
774 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
775 if (EFI_ERROR (Status
)) {
776 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid iSCSI Name!", NULL
);
778 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
783 case KEY_DHCP_ENABLE
:
784 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
785 IfrNvData
->TargetInfoFromDhcp
= 0;
791 IScsiUnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
792 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
793 if (EFI_ERROR (Status
)) {
794 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid LUN string!", NULL
);
796 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
802 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPName
, Private
->Current
->AuthConfigData
.CHAPName
);
805 case KEY_CHAP_SECRET
:
806 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPSecret
, Private
->Current
->AuthConfigData
.CHAPSecret
);
809 case KEY_REVERSE_CHAP_NAME
:
810 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPName
, Private
->Current
->AuthConfigData
.ReverseCHAPName
);
813 case KEY_REVERSE_CHAP_SECRET
:
814 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPSecret
, Private
->Current
->AuthConfigData
.ReverseCHAPSecret
);
817 case KEY_CONFIG_ISID
:
818 IScsiParseIsIdFromString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
819 IScsiConvertIsIdToString (IfrNvData
->IsId
, Private
->Current
->SessionConfigData
.IsId
);
823 case KEY_SAVE_CHANGES
:
825 // First, update those fields which don't have INTERACTIVE set.
827 Private
->Current
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
828 Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
829 Private
->Current
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
830 if (Private
->Current
->SessionConfigData
.TargetPort
== 0) {
831 Private
->Current
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
834 Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
835 Private
->Current
->AuthConfigData
.CHAPType
= IfrNvData
->CHAPType
;
838 // Only do full parameter validation if iSCSI is enabled on this device.
840 if (Private
->Current
->SessionConfigData
.Enabled
) {
842 // Validate the address configuration of the Initiator if DHCP isn't
845 if (!Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
) {
846 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
847 CopyMem (&SubnetMask
.v4
, &Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
848 CopyMem (&Gateway
.v4
, &Private
->Current
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
850 if ((Gateway
.Addr
[0] != 0)) {
851 if (SubnetMask
.Addr
[0] == 0) {
852 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Gateway address is set but subnet mask is zero.", NULL
);
853 Status
= EFI_INVALID_PARAMETER
;
855 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
856 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Local IP and Gateway are not in the same subnet.", NULL
);
857 Status
= EFI_INVALID_PARAMETER
;
863 // Validate target configuration if DHCP isn't deployed.
865 if (!Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
) {
866 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.TargetIp
, sizeof (HostIp
.v4
));
867 if (!NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
868 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Target IP is invalid!", NULL
);
869 Status
= EFI_INVALID_PARAMETER
;
874 if (IfrNvData
->CHAPType
!= ISCSI_CHAP_NONE
) {
875 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
876 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"CHAP Name or CHAP Secret is invalid!", NULL
);
877 Status
= EFI_INVALID_PARAMETER
;
881 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
882 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
884 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!", NULL
);
885 Status
= EFI_INVALID_PARAMETER
;
891 BufferSize
= sizeof (Private
->Current
->SessionConfigData
);
893 Private
->Current
->MacString
,
894 &gEfiIScsiInitiatorNameProtocolGuid
,
895 ISCSI_CONFIG_VAR_ATTR
,
897 &Private
->Current
->SessionConfigData
900 BufferSize
= sizeof (Private
->Current
->AuthConfigData
);
902 Private
->Current
->MacString
,
903 &gIScsiCHAPAuthInfoGuid
,
904 ISCSI_CONFIG_VAR_ATTR
,
906 &Private
->Current
->AuthConfigData
908 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
916 if (!EFI_ERROR (Status
)) {
918 // Pass changed uncommitted data back to Form Browser
920 HiiSetBrowserData (&gIp4IScsiConfigGuid
, mVendorStorageName
, sizeof (ISCSI_CONFIG_IFR_NVDATA
), (UINT8
*) IfrNvData
, NULL
);
923 FreePool (IfrNvData
);
929 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
930 device specified by the Controller.
932 @param[in] DriverBindingHandle The driverbinding handle.
933 @param[in] Controller The controller handle of the iSCSI device.
934 @param[in] AddForm Whether to add or delete a form entry.
936 @retval EFI_SUCCESS The iSCSI configuration form is updated.
937 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
938 @retval Others Other errors as indicated.
941 IScsiConfigUpdateForm (
942 IN EFI_HANDLE DriverBindingHandle
,
943 IN EFI_HANDLE Controller
,
948 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
949 BOOLEAN EntryExisted
;
951 EFI_MAC_ADDRESS MacAddress
;
954 CHAR16 PortString
[128];
957 VOID
*StartOpCodeHandle
;
958 VOID
*EndOpCodeHandle
;
959 EFI_IFR_GUID_LABEL
*StartLabel
;
960 EFI_IFR_GUID_LABEL
*EndLabel
;
962 ConfigFormEntry
= NULL
;
963 EntryExisted
= FALSE
;
965 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
966 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
968 if (ConfigFormEntry
->Controller
== Controller
) {
981 ConfigFormEntry
= (ISCSI_CONFIG_FORM_ENTRY
*) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY
));
982 if (ConfigFormEntry
== NULL
) {
983 return EFI_OUT_OF_RESOURCES
;
986 InitializeListHead (&ConfigFormEntry
->Link
);
987 ConfigFormEntry
->Controller
= Controller
;
990 // Get the MAC address and convert it into the formatted string.
992 Status
= NetLibGetMacAddress (Controller
, &MacAddress
, &HwAddressSize
);
993 ASSERT (Status
== EFI_SUCCESS
);
994 VlanId
= NetLibGetVlanId (Controller
);
996 IScsiMacAddrToStr (&MacAddress
, (UINT32
) HwAddressSize
, VlanId
, ConfigFormEntry
->MacString
);
999 // Get the normal session configuration data.
1001 BufferSize
= sizeof (ConfigFormEntry
->SessionConfigData
);
1002 Status
= gRT
->GetVariable (
1003 ConfigFormEntry
->MacString
,
1004 &gEfiIScsiInitiatorNameProtocolGuid
,
1007 &ConfigFormEntry
->SessionConfigData
1009 if (EFI_ERROR (Status
)) {
1010 ZeroMem (&ConfigFormEntry
->SessionConfigData
, sizeof (ConfigFormEntry
->SessionConfigData
));
1013 // Generate OUI-format ISID based on MAC address.
1015 CopyMem (ConfigFormEntry
->SessionConfigData
.IsId
, &MacAddress
, 6);
1016 ConfigFormEntry
->SessionConfigData
.IsId
[0] =
1017 (UINT8
) (ConfigFormEntry
->SessionConfigData
.IsId
[0] & 0x3F);
1020 // Get the CHAP authentication configuration data.
1022 BufferSize
= sizeof (ConfigFormEntry
->AuthConfigData
);
1023 Status
= gRT
->GetVariable (
1024 ConfigFormEntry
->MacString
,
1025 &gIScsiCHAPAuthInfoGuid
,
1028 &ConfigFormEntry
->AuthConfigData
1030 if (EFI_ERROR (Status
)) {
1031 ZeroMem (&ConfigFormEntry
->AuthConfigData
, sizeof (ConfigFormEntry
->AuthConfigData
));
1034 // Compose the Port string and create a new EFI_STRING_ID.
1036 UnicodeSPrint (PortString
, 128, L
"Port %s", ConfigFormEntry
->MacString
);
1037 ConfigFormEntry
->PortTitleToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, PortString
, NULL
);
1040 // Compose the help string of this port and create a new EFI_STRING_ID.
1042 UnicodeSPrint (PortString
, 128, L
"Set the iSCSI parameters on port %s", ConfigFormEntry
->MacString
);
1043 ConfigFormEntry
->PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, PortString
, NULL
);
1045 InsertTailList (&mIScsiConfigFormList
, &ConfigFormEntry
->Link
);
1046 mNumberOfIScsiDevices
++;
1049 ASSERT (EntryExisted
);
1051 mNumberOfIScsiDevices
--;
1052 RemoveEntryList (&ConfigFormEntry
->Link
);
1053 FreePool (ConfigFormEntry
);
1056 // Allocate space for creation of Buffer
1060 // Init OpCode Handle
1062 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1063 ASSERT (StartOpCodeHandle
!= NULL
);
1065 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1066 ASSERT (EndOpCodeHandle
!= NULL
);
1069 // Create Hii Extend Label OpCode as the start opcode
1071 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1072 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1073 StartLabel
->Number
= DEVICE_ENTRY_LABEL
;
1076 // Create Hii Extend Label OpCode as the end opcode
1078 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
1079 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1080 EndLabel
->Number
= LABEL_END
;
1083 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
1084 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
1086 HiiCreateGotoOpCode (
1087 StartOpCodeHandle
, // Container for dynamic created opcodes
1088 FORMID_DEVICE_FORM
, // Target Form ID
1089 ConfigFormEntry
->PortTitleToken
, // Prompt text
1090 ConfigFormEntry
->PortTitleHelpToken
, // Help text
1091 EFI_IFR_FLAG_CALLBACK
, // Question flag
1092 (UINT16
)(KEY_DEVICE_ENTRY_BASE
+ FormIndex
) // Question ID
1099 mCallbackInfo
->RegisteredHandle
,
1100 &gIp4IScsiConfigGuid
,
1102 StartOpCodeHandle
, // Label DEVICE_ENTRY_LABEL
1103 EndOpCodeHandle
// LABEL_END
1106 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1107 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1113 Initialize the iSCSI configuration form.
1115 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
1117 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
1118 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1119 @retval Others Other errors as indicated.
1122 IScsiConfigFormInit (
1127 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
1128 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
1130 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**)&HiiDatabase
);
1131 if (EFI_ERROR (Status
)) {
1135 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
1136 if (CallbackInfo
== NULL
) {
1137 return EFI_OUT_OF_RESOURCES
;
1140 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
1141 CallbackInfo
->HiiDatabase
= HiiDatabase
;
1142 CallbackInfo
->Current
= NULL
;
1144 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
1145 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
1146 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
1148 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**)&CallbackInfo
->ConfigRouting
);
1149 if (EFI_ERROR (Status
)) {
1150 FreePool(CallbackInfo
);
1155 // Install Device Path Protocol and Config Access protocol to driver handle
1157 Status
= gBS
->InstallMultipleProtocolInterfaces (
1158 &CallbackInfo
->DriverHandle
,
1159 &gEfiDevicePathProtocolGuid
,
1160 &mIScsiHiiVendorDevicePath
,
1161 &gEfiHiiConfigAccessProtocolGuid
,
1162 &CallbackInfo
->ConfigAccess
,
1165 ASSERT_EFI_ERROR (Status
);
1168 // Publish our HII data
1170 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
1171 &gIp4IScsiConfigGuid
,
1172 CallbackInfo
->DriverHandle
,
1177 if (CallbackInfo
->RegisteredHandle
== NULL
) {
1178 FreePool(CallbackInfo
);
1179 return EFI_OUT_OF_RESOURCES
;
1182 mCallbackInfo
= CallbackInfo
;
1188 Unload the iSCSI configuration form, this includes: delete all the iSCSI
1189 device configuration entries, uninstall the form callback protocol and
1190 free the resources used.
1192 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
1194 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
1195 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1198 IScsiConfigFormUnload (
1199 IN EFI_HANDLE DriverBindingHandle
1202 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
1204 while (!IsListEmpty (&mIScsiConfigFormList
)) {
1206 // Uninstall the device forms as the iSCSI driver instance may fail to
1207 // control the controller but still install the device configuration form.
1208 // In such case, upon driver unloading, the driver instance's driverbinding.
1209 // stop () won't be called, so we have to take this chance here to uninstall
1212 ConfigFormEntry
= NET_LIST_USER_STRUCT (mIScsiConfigFormList
.ForwardLink
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
1213 IScsiConfigUpdateForm (DriverBindingHandle
, ConfigFormEntry
->Controller
, FALSE
);
1217 // Remove HII package list
1219 mCallbackInfo
->HiiDatabase
->RemovePackageList (
1220 mCallbackInfo
->HiiDatabase
,
1221 mCallbackInfo
->RegisteredHandle
1225 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
1227 gBS
->UninstallMultipleProtocolInterfaces (
1228 mCallbackInfo
->DriverHandle
,
1229 &gEfiDevicePathProtocolGuid
,
1230 &mIScsiHiiVendorDevicePath
,
1231 &gEfiHiiConfigAccessProtocolGuid
,
1232 &mCallbackInfo
->ConfigAccess
,
1235 FreePool (mCallbackInfo
);