2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2010, 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 EFI_GUID mVendorGuid
= ISCSI_CONFIG_GUID
;
18 CHAR16 mVendorStorageName
[] = L
"ISCSI_CONFIG_IFR_NVDATA";
19 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
20 UINTN mNumberOfIScsiDevices
= 0;
21 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
23 LIST_ENTRY mIScsiConfigFormList
= {
24 &mIScsiConfigFormList
,
28 HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath
= {
34 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
39 // {49D7B73E-143D-4716-977B-C45F1CB038CC}
41 { 0x49d7b73e, 0x143d, 0x4716, { 0x97, 0x7b, 0xc4, 0x5f, 0x1c, 0xb0, 0x38, 0xcc } }
45 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
47 (UINT8
) (END_DEVICE_PATH_LENGTH
),
48 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
54 Convert the IPv4 address into a dotted string.
56 @param[in] Ip The IPv4 address.
57 @param[out] Str The dotted IP string.
61 IN EFI_IPv4_ADDRESS
*Ip
,
65 UnicodeSPrint ( Str
, 2 * IP4_STR_MAX_SIZE
, L
"%d.%d.%d.%d", Ip
->Addr
[0], Ip
->Addr
[1], Ip
->Addr
[2], Ip
->Addr
[3]);
69 Update the list of iSCSI devices the iSCSI driver is controlling.
71 @retval EFI_SUCCESS The callback successfully handled the action.
72 @retval Others Other errors as indicated.
75 IScsiUpdateDeviceList (
80 ISCSI_DEVICE_LIST
*DeviceList
;
86 UINTN LastDeviceIndex
;
87 EFI_MAC_ADDRESS MacAddress
;
90 ISCSI_MAC_INFO
*CurMacInfo
;
91 ISCSI_MAC_INFO TempMacInfo
;
96 // Dump all the handles the Managed Network Service Binding Protocol is installed on.
98 Status
= gBS
->LocateHandleBuffer (
100 &gEfiManagedNetworkServiceBindingProtocolGuid
,
105 if (EFI_ERROR (Status
)) {
110 Status
= gRT
->GetVariable (
117 if (Status
== EFI_BUFFER_TOO_SMALL
) {
118 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DataSize
);
130 for (HandleIndex
= 0; HandleIndex
< NumHandles
; HandleIndex
++) {
131 Status
= NetLibGetMacAddress (Handles
[HandleIndex
], &MacAddress
, &HwAddressSize
);
132 ASSERT (Status
== EFI_SUCCESS
);
133 VlanId
= NetLibGetVlanId (Handles
[HandleIndex
]);
135 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
136 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
137 if ((CurMacInfo
->Len
== HwAddressSize
) &&
138 (CurMacInfo
->VlanId
== VlanId
) &&
139 (NET_MAC_EQUAL (&CurMacInfo
->Mac
, MacAddress
.Addr
, HwAddressSize
))
142 // The previous configured NIC is still here.
144 if (Index
!= LastDeviceIndex
) {
146 // Swap the current MAC address entry with the one indexed by
149 CopyMem (&TempMacInfo
, CurMacInfo
, sizeof (ISCSI_MAC_INFO
));
150 CopyMem (CurMacInfo
, &DeviceList
->MacInfo
[LastDeviceIndex
], sizeof (ISCSI_MAC_INFO
));
151 CopyMem (&DeviceList
->MacInfo
[LastDeviceIndex
], &TempMacInfo
, sizeof (ISCSI_MAC_INFO
));
158 if (LastDeviceIndex
== DeviceList
->NumDevice
) {
163 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
165 // delete the variables
167 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
168 IScsiMacAddrToStr (&CurMacInfo
->Mac
, CurMacInfo
->Len
, CurMacInfo
->VlanId
, MacString
);
169 gRT
->SetVariable (MacString
, &gEfiIScsiInitiatorNameProtocolGuid
, 0, 0, NULL
);
170 gRT
->SetVariable (MacString
, &mIScsiCHAPAuthInfoGuid
, 0, 0, NULL
);
173 FreePool (DeviceList
);
174 } else if (Status
!= EFI_NOT_FOUND
) {
179 // Construct the new iSCSI device list.
181 DeviceListSize
= sizeof (ISCSI_DEVICE_LIST
) + (NumHandles
- 1) * sizeof (ISCSI_MAC_INFO
);
182 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DeviceListSize
);
183 DeviceList
->NumDevice
= (UINT8
) NumHandles
;
185 for (Index
= 0; Index
< NumHandles
; Index
++) {
186 NetLibGetMacAddress (Handles
[Index
], &MacAddress
, &HwAddressSize
);
188 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
189 CopyMem (&CurMacInfo
->Mac
, MacAddress
.Addr
, HwAddressSize
);
190 CurMacInfo
->Len
= (UINT8
) HwAddressSize
;
191 CurMacInfo
->VlanId
= NetLibGetVlanId (Handles
[Index
]);
197 ISCSI_CONFIG_VAR_ATTR
,
202 FreePool (DeviceList
);
209 Get the iSCSI configuration form entry by the index of the goto opcode actived.
211 @param[in] Index The 0-based index of the goto opcode actived.
213 @return The iSCSI configuration form entry found.
215 ISCSI_CONFIG_FORM_ENTRY
*
216 IScsiGetConfigFormEntryByIndex (
222 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
225 ConfigFormEntry
= NULL
;
227 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
228 if (CurrentIndex
== Index
) {
229 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
236 return ConfigFormEntry
;
240 Convert the iSCSI configuration data into the IFR data.
242 @param[in] ConfigFormEntry The iSCSI configuration form entry.
243 @param[out] IfrNvData The IFR nv data.
246 IScsiConvertDeviceConfigDataToIfrNvData (
247 IN ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
248 OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
251 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
252 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
255 // Normal session configuration parameters.
257 SessionConfigData
= &ConfigFormEntry
->SessionConfigData
;
258 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
260 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
261 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
262 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
264 IScsiIpToStr (&SessionConfigData
->LocalIp
, IfrNvData
->LocalIp
);
265 IScsiIpToStr (&SessionConfigData
->SubnetMask
, IfrNvData
->SubnetMask
);
266 IScsiIpToStr (&SessionConfigData
->Gateway
, IfrNvData
->Gateway
);
267 IScsiIpToStr (&SessionConfigData
->TargetIp
, IfrNvData
->TargetIp
);
269 IScsiAsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
271 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
274 // CHAP authentication parameters.
276 AuthConfigData
= &ConfigFormEntry
->AuthConfigData
;
278 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
280 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
281 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
282 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
283 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
287 This function allows the caller to request the current
288 configuration for one or more named elements. The resulting
289 string is in <ConfigAltResp> format. Any and all alternative
290 configuration strings shall also be appended to the end of the
291 current configuration string. If they are, they must appear
292 after the current configuration. They must contain the same
293 routing (GUID, NAME, PATH) as the current configuration string.
294 They must have an additional description indicating the type of
295 alternative configuration the string represents,
296 "ALTCFG=<StringToken>". That <StringToken> (when
297 converted from Hex UNICODE to binary) is a reference to a
298 string in the associated string pack.
300 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
301 @param[in] Request A null-terminated Unicode string in
302 <ConfigRequest> format. Note that this
303 includes the routing information as well as
304 the configurable name / value pairs. It is
305 invalid for this string to be in
306 <MultiConfigRequest> format.
307 @param[out] Progress On return, points to a character in the
308 Request string. Points to the string's null
309 terminator if request was successful. Points
310 to the most recent "&" before the first
311 failing name / value pair (or the beginning
312 of the string if the failure is in the first
313 name / value pair) if the request was not
315 @param[out] Results A null-terminated Unicode string in
316 <ConfigAltResp> format which has all values
317 filled in for the names in the Request string.
318 String to be allocated by the called function.
320 @retval EFI_SUCCESS The Results string is filled with the
321 values corresponding to all requested
323 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
324 parts of the results that must be
325 stored awaiting possible future
327 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
328 for the Request parameter
329 would result in this type of
330 error. In this case, the
331 Progress parameter would be
333 @retval EFI_NOT_FOUND Routing data doesn't match any
334 known driver. Progress set to the
335 first character in the routing header.
336 Note: There is no requirement that the
337 driver validate the routing data. It
338 must skip the <ConfigHdr> in order to
340 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
341 to most recent & before the
342 error or the beginning of the
344 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
345 to the & before the name in
346 question.Currently not implemented.
350 IScsiFormExtractConfig (
351 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
352 IN CONST EFI_STRING Request
,
353 OUT EFI_STRING
*Progress
,
354 OUT EFI_STRING
*Results
358 CHAR8 InitiatorName
[ISCSI_NAME_IFR_MAX_SIZE
];
360 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
361 ISCSI_FORM_CALLBACK_INFO
*Private
;
362 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
363 EFI_STRING ConfigRequestHdr
;
364 EFI_STRING ConfigRequest
;
365 BOOLEAN AllocatedRequest
;
368 if (Progress
== NULL
|| Results
== NULL
) {
369 return EFI_INVALID_PARAMETER
;
373 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &mVendorGuid
, mVendorStorageName
)) {
374 return EFI_NOT_FOUND
;
377 ConfigRequestHdr
= NULL
;
378 ConfigRequest
= NULL
;
379 AllocatedRequest
= FALSE
;
382 if (!mIScsiDeviceListUpdated
) {
384 // Update the device list.
386 IScsiUpdateDeviceList ();
387 mIScsiDeviceListUpdated
= TRUE
;
390 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
391 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
392 ASSERT (IfrNvData
!= NULL
);
393 if (Private
->Current
!= NULL
) {
394 IScsiConvertDeviceConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
397 BufferSize
= ISCSI_NAME_IFR_MAX_SIZE
;
398 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
399 if (EFI_ERROR (Status
)) {
400 IfrNvData
->InitiatorName
[0] = L
'\0';
402 IScsiAsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
406 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
408 HiiConfigRouting
= Private
->ConfigRouting
;
409 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
410 ConfigRequest
= Request
;
411 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
413 // Request has no request element, construct full request string.
414 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
415 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
417 ConfigRequestHdr
= HiiConstructConfigHdr (&mVendorGuid
, mVendorStorageName
, Private
->DriverHandle
);
418 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
419 ConfigRequest
= AllocateZeroPool (Size
);
420 ASSERT (ConfigRequest
!= NULL
);
421 AllocatedRequest
= TRUE
;
422 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
423 FreePool (ConfigRequestHdr
);
425 Status
= HiiConfigRouting
->BlockToConfig (
433 FreePool (IfrNvData
);
435 // Free the allocated config request string.
437 if (AllocatedRequest
) {
438 FreePool (ConfigRequest
);
439 ConfigRequest
= NULL
;
443 // Set Progress string to the original request string.
445 if (Request
== NULL
) {
447 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
448 *Progress
= Request
+ StrLen (Request
);
455 This function applies changes in a driver's configuration.
456 Input is a Configuration, which has the routing data for this
457 driver followed by name / value configuration pairs. The driver
458 must apply those pairs to its configurable storage. If the
459 driver's configuration is stored in a linear block of data
460 and the driver's name / value pairs are in <BlockConfig>
461 format, it may use the ConfigToBlock helper function (above) to
462 simplify the job. Currently not implemented.
464 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
465 @param[in] Configuration A null-terminated Unicode string in
466 <ConfigString> format.
467 @param[out] Progress A pointer to a string filled in with the
468 offset of the most recent '&' before the
469 first failing name / value pair (or the
470 beginn ing of the string if the failure
471 is in the first name / value pair) or
472 the terminating NULL if all was
475 @retval EFI_SUCCESS The results have been distributed or are
476 awaiting distribution.
477 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
478 parts of the results that must be
479 stored awaiting possible future
481 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
482 Results parameter would result
483 in this type of error.
484 @retval EFI_NOT_FOUND Target for the specified routing data
489 IScsiFormRouteConfig (
490 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
491 IN CONST EFI_STRING Configuration
,
492 OUT EFI_STRING
*Progress
495 if (Configuration
== NULL
|| Progress
== NULL
) {
496 return EFI_INVALID_PARAMETER
;
500 // Check routing data in <ConfigHdr>.
501 // Note: if only one Storage is used, then this checking could be skipped.
503 if (!HiiIsConfigHdrMatch (Configuration
, &mVendorGuid
, mVendorStorageName
)) {
504 *Progress
= Configuration
;
505 return EFI_NOT_FOUND
;
508 *Progress
= Configuration
+ StrLen (Configuration
);
513 This function is called to provide results data to the driver.
514 This data consists of a unique key that is used to identify
515 which data is either being passed back or being asked for.
517 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
518 @param[in] Action Specifies the type of action taken by the browser.
519 @param[in] QuestionId A unique value which is sent to the original
520 exporting driver so that it can identify the type
521 of data to expect. The format of the data tends to
522 vary based on the opcode that enerated the callback.
523 @param[in] Type The type of value for the question.
524 @param[in] Value A pointer to the data being sent to the original
526 @param[out] ActionRequest On return, points to the action requested by the
529 @retval EFI_SUCCESS The callback successfully handled the action.
530 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
531 variable and its data.
532 @retval EFI_DEVICE_ERROR The variable could not be saved.
533 @retval EFI_UNSUPPORTED The specified Action is not supported by the
534 callback.Currently not implemented.
535 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
536 @retval Others Other errors as indicated.
541 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
542 IN EFI_BROWSER_ACTION Action
,
543 IN EFI_QUESTION_ID QuestionId
,
545 IN EFI_IFR_TYPE_VALUE
*Value
,
546 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
549 ISCSI_FORM_CALLBACK_INFO
*Private
;
551 CHAR8 IScsiName
[ISCSI_NAME_IFR_MAX_SIZE
];
552 CHAR16 PortString
[128];
553 CHAR8 Ip4String
[IP4_STR_MAX_SIZE
];
554 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
556 EFI_STRING_ID DeviceFormTitleToken
;
557 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
558 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
559 EFI_IP_ADDRESS HostIp
;
560 EFI_IP_ADDRESS SubnetMask
;
561 EFI_IP_ADDRESS Gateway
;
565 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
568 // Retrive uncommitted data from Browser
570 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
571 ASSERT (IfrNvData
!= NULL
);
572 if (!HiiGetBrowserData (&mVendorGuid
, mVendorStorageName
, sizeof (ISCSI_CONFIG_IFR_NVDATA
), (UINT8
*) IfrNvData
)) {
573 FreePool (IfrNvData
);
574 return EFI_NOT_FOUND
;
577 Status
= EFI_SUCCESS
;
579 switch (QuestionId
) {
580 case KEY_INITIATOR_NAME
:
581 IScsiUnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
582 BufferSize
= AsciiStrLen (IScsiName
) + 1;
584 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
585 if (EFI_ERROR (Status
)) {
586 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid iSCSI Name!", NULL
);
592 IScsiUnicodeStrToAsciiStr (IfrNvData
->LocalIp
, Ip4String
);
593 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
594 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
595 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid IP address!", NULL
);
596 Status
= EFI_INVALID_PARAMETER
;
598 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
603 case KEY_SUBNET_MASK
:
604 IScsiUnicodeStrToAsciiStr (IfrNvData
->SubnetMask
, Ip4String
);
605 Status
= IScsiAsciiStrToIp (Ip4String
, &SubnetMask
.v4
);
606 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
607 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid Subnet Mask!", NULL
);
608 Status
= EFI_INVALID_PARAMETER
;
610 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
616 IScsiUnicodeStrToAsciiStr (IfrNvData
->Gateway
, Ip4String
);
617 Status
= IScsiAsciiStrToIp (Ip4String
, &Gateway
.v4
);
618 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
619 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid Gateway!", NULL
);
620 Status
= EFI_INVALID_PARAMETER
;
622 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
628 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetIp
, Ip4String
);
629 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
630 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
631 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid IP address!", NULL
);
632 Status
= EFI_INVALID_PARAMETER
;
634 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
639 case KEY_TARGET_NAME
:
640 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
641 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
642 if (EFI_ERROR (Status
)) {
643 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid iSCSI Name!", NULL
);
645 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
650 case KEY_DHCP_ENABLE
:
651 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
652 IfrNvData
->TargetInfoFromDhcp
= 0;
658 IScsiUnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
659 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
660 if (EFI_ERROR (Status
)) {
661 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid LUN string!", NULL
);
663 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
669 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPName
, Private
->Current
->AuthConfigData
.CHAPName
);
672 case KEY_CHAP_SECRET
:
673 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPSecret
, Private
->Current
->AuthConfigData
.CHAPSecret
);
676 case KEY_REVERSE_CHAP_NAME
:
677 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPName
, Private
->Current
->AuthConfigData
.ReverseCHAPName
);
680 case KEY_REVERSE_CHAP_SECRET
:
681 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPSecret
, Private
->Current
->AuthConfigData
.ReverseCHAPSecret
);
684 case KEY_SAVE_CHANGES
:
686 // First, update those fields which don't have INTERACTIVE set.
688 Private
->Current
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
689 Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
690 Private
->Current
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
691 if (Private
->Current
->SessionConfigData
.TargetPort
== 0) {
692 Private
->Current
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
695 Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
696 Private
->Current
->AuthConfigData
.CHAPType
= IfrNvData
->CHAPType
;
699 // Only do full parameter validation if iSCSI is enabled on this device.
701 if (Private
->Current
->SessionConfigData
.Enabled
) {
703 // Validate the address configuration of the Initiator if DHCP isn't
706 if (!Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
) {
707 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
708 CopyMem (&SubnetMask
.v4
, &Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
709 CopyMem (&Gateway
.v4
, &Private
->Current
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
711 if ((Gateway
.Addr
[0] != 0)) {
712 if (SubnetMask
.Addr
[0] == 0) {
713 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Gateway address is set but subnet mask is zero.", NULL
);
714 Status
= EFI_INVALID_PARAMETER
;
716 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
717 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Local IP and Gateway are not in the same subnet.", NULL
);
718 Status
= EFI_INVALID_PARAMETER
;
724 // Validate target configuration if DHCP isn't deployed.
726 if (!Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
) {
727 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.TargetIp
, sizeof (HostIp
.v4
));
728 if (!NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
729 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Target IP is invalid!", NULL
);
730 Status
= EFI_INVALID_PARAMETER
;
735 if (IfrNvData
->CHAPType
!= ISCSI_CHAP_NONE
) {
736 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
737 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"CHAP Name or CHAP Secret is invalid!", NULL
);
738 Status
= EFI_INVALID_PARAMETER
;
742 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
743 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
745 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!", NULL
);
746 Status
= EFI_INVALID_PARAMETER
;
752 BufferSize
= sizeof (Private
->Current
->SessionConfigData
);
754 Private
->Current
->MacString
,
755 &gEfiIScsiInitiatorNameProtocolGuid
,
756 ISCSI_CONFIG_VAR_ATTR
,
758 &Private
->Current
->SessionConfigData
761 BufferSize
= sizeof (Private
->Current
->AuthConfigData
);
763 Private
->Current
->MacString
,
764 &mIScsiCHAPAuthInfoGuid
,
765 ISCSI_CONFIG_VAR_ATTR
,
767 &Private
->Current
->AuthConfigData
769 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
773 if ((QuestionId
>= KEY_DEVICE_ENTRY_BASE
) && (QuestionId
< (mNumberOfIScsiDevices
+ KEY_DEVICE_ENTRY_BASE
))) {
775 // In case goto the device configuration form, update the device form title.
777 ConfigFormEntry
= IScsiGetConfigFormEntryByIndex ((UINT32
) (QuestionId
- KEY_DEVICE_ENTRY_BASE
));
778 ASSERT (ConfigFormEntry
!= NULL
);
780 UnicodeSPrint (PortString
, (UINTN
) 128, L
"Port %s", ConfigFormEntry
->MacString
);
781 DeviceFormTitleToken
= (EFI_STRING_ID
) STR_ISCSI_DEVICE_FORM_TITLE
;
782 HiiSetString (Private
->RegisteredHandle
, DeviceFormTitleToken
, PortString
, NULL
);
784 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry
, IfrNvData
);
786 Private
->Current
= ConfigFormEntry
;
792 if (!EFI_ERROR (Status
)) {
794 // Pass changed uncommitted data back to Form Browser
796 HiiSetBrowserData (&mVendorGuid
, mVendorStorageName
, sizeof (ISCSI_CONFIG_IFR_NVDATA
), (UINT8
*) IfrNvData
, NULL
);
799 FreePool (IfrNvData
);
804 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
805 device specified by the Controller.
807 @param[in] DriverBindingHandle The driverbinding handle.
808 @param[in] Controller The controller handle of the iSCSI device.
809 @param[in] AddForm Whether to add or delete a form entry.
811 @retval EFI_SUCCESS The iSCSI configuration form is updated.
812 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
813 @retval Others Other errors as indicated.
816 IScsiConfigUpdateForm (
817 IN EFI_HANDLE DriverBindingHandle
,
818 IN EFI_HANDLE Controller
,
823 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
824 BOOLEAN EntryExisted
;
826 EFI_MAC_ADDRESS MacAddress
;
829 CHAR16 PortString
[128];
832 VOID
*StartOpCodeHandle
;
833 VOID
*EndOpCodeHandle
;
834 EFI_IFR_GUID_LABEL
*StartLabel
;
835 EFI_IFR_GUID_LABEL
*EndLabel
;
837 ConfigFormEntry
= NULL
;
838 EntryExisted
= FALSE
;
840 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
841 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
843 if (ConfigFormEntry
->Controller
== Controller
) {
856 ConfigFormEntry
= (ISCSI_CONFIG_FORM_ENTRY
*) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY
));
857 if (ConfigFormEntry
== NULL
) {
858 return EFI_OUT_OF_RESOURCES
;
861 InitializeListHead (&ConfigFormEntry
->Link
);
862 ConfigFormEntry
->Controller
= Controller
;
865 // Get the MAC address and convert it into the formatted string.
867 Status
= NetLibGetMacAddress (Controller
, &MacAddress
, &HwAddressSize
);
868 ASSERT (Status
== EFI_SUCCESS
);
869 VlanId
= NetLibGetVlanId (Controller
);
871 IScsiMacAddrToStr (&MacAddress
, (UINT32
) HwAddressSize
, VlanId
, ConfigFormEntry
->MacString
);
874 // Get the normal session configuration data.
876 BufferSize
= sizeof (ConfigFormEntry
->SessionConfigData
);
877 Status
= gRT
->GetVariable (
878 ConfigFormEntry
->MacString
,
879 &gEfiIScsiInitiatorNameProtocolGuid
,
882 &ConfigFormEntry
->SessionConfigData
884 if (EFI_ERROR (Status
)) {
885 ZeroMem (&ConfigFormEntry
->SessionConfigData
, sizeof (ConfigFormEntry
->SessionConfigData
));
888 // Get the CHAP authentication configuration data.
890 BufferSize
= sizeof (ConfigFormEntry
->AuthConfigData
);
891 Status
= gRT
->GetVariable (
892 ConfigFormEntry
->MacString
,
893 &mIScsiCHAPAuthInfoGuid
,
896 &ConfigFormEntry
->AuthConfigData
898 if (EFI_ERROR (Status
)) {
899 ZeroMem (&ConfigFormEntry
->AuthConfigData
, sizeof (ConfigFormEntry
->AuthConfigData
));
902 // Compose the Port string and create a new EFI_STRING_ID.
904 UnicodeSPrint (PortString
, 128, L
"Port %s", ConfigFormEntry
->MacString
);
905 ConfigFormEntry
->PortTitleToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, PortString
, NULL
);
908 // Compose the help string of this port and create a new EFI_STRING_ID.
910 UnicodeSPrint (PortString
, 128, L
"Set the iSCSI parameters on port %s", ConfigFormEntry
->MacString
);
911 ConfigFormEntry
->PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, PortString
, NULL
);
913 InsertTailList (&mIScsiConfigFormList
, &ConfigFormEntry
->Link
);
914 mNumberOfIScsiDevices
++;
917 ASSERT (EntryExisted
);
919 mNumberOfIScsiDevices
--;
920 RemoveEntryList (&ConfigFormEntry
->Link
);
921 FreePool (ConfigFormEntry
);
924 // Allocate space for creation of Buffer
928 // Init OpCode Handle
930 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
931 ASSERT (StartOpCodeHandle
!= NULL
);
933 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
934 ASSERT (EndOpCodeHandle
!= NULL
);
937 // Create Hii Extend Label OpCode as the start opcode
939 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
940 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
941 StartLabel
->Number
= DEVICE_ENTRY_LABEL
;
944 // Create Hii Extend Label OpCode as the end opcode
946 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
947 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
948 EndLabel
->Number
= LABEL_END
;
951 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
952 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
954 HiiCreateGotoOpCode (
955 StartOpCodeHandle
, // Container for dynamic created opcodes
956 FORMID_DEVICE_FORM
, // Target Form ID
957 ConfigFormEntry
->PortTitleToken
, // Prompt text
958 ConfigFormEntry
->PortTitleHelpToken
, // Help text
959 EFI_IFR_FLAG_CALLBACK
, // Question flag
960 (UINT16
)(KEY_DEVICE_ENTRY_BASE
+ FormIndex
) // Question ID
967 mCallbackInfo
->RegisteredHandle
,
970 StartOpCodeHandle
, // Label DEVICE_ENTRY_LABEL
971 EndOpCodeHandle
// LABEL_END
974 HiiFreeOpCodeHandle (StartOpCodeHandle
);
975 HiiFreeOpCodeHandle (EndOpCodeHandle
);
981 Initialize the iSCSI configuration form.
983 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
985 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
986 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
987 @retval Others Other errors as indicated.
990 IScsiConfigFormInit (
995 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
996 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
998 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**)&HiiDatabase
);
999 if (EFI_ERROR (Status
)) {
1003 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
1004 if (CallbackInfo
== NULL
) {
1005 return EFI_OUT_OF_RESOURCES
;
1008 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
1009 CallbackInfo
->HiiDatabase
= HiiDatabase
;
1010 CallbackInfo
->Current
= NULL
;
1012 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
1013 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
1014 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
1016 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**)&CallbackInfo
->ConfigRouting
);
1017 if (EFI_ERROR (Status
)) {
1018 FreePool(CallbackInfo
);
1023 // Install Device Path Protocol and Config Access protocol to driver handle
1025 Status
= gBS
->InstallMultipleProtocolInterfaces (
1026 &CallbackInfo
->DriverHandle
,
1027 &gEfiDevicePathProtocolGuid
,
1028 &mIScsiHiiVendorDevicePath
,
1029 &gEfiHiiConfigAccessProtocolGuid
,
1030 &CallbackInfo
->ConfigAccess
,
1033 ASSERT_EFI_ERROR (Status
);
1036 // Publish our HII data
1038 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
1040 CallbackInfo
->DriverHandle
,
1045 if (CallbackInfo
->RegisteredHandle
== NULL
) {
1046 FreePool(CallbackInfo
);
1047 return EFI_OUT_OF_RESOURCES
;
1050 mCallbackInfo
= CallbackInfo
;
1056 Unload the iSCSI configuration form, this includes: delete all the iSCSI
1057 device configuration entries, uninstall the form callback protocol and
1058 free the resources used.
1060 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
1062 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
1063 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1066 IScsiConfigFormUnload (
1067 IN EFI_HANDLE DriverBindingHandle
1070 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
1072 while (!IsListEmpty (&mIScsiConfigFormList
)) {
1074 // Uninstall the device forms as the iSCSI driver instance may fail to
1075 // control the controller but still install the device configuration form.
1076 // In such case, upon driver unloading, the driver instance's driverbinding.
1077 // stop () won't be called, so we have to take this chance here to uninstall
1080 ConfigFormEntry
= NET_LIST_USER_STRUCT (mIScsiConfigFormList
.ForwardLink
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
1081 IScsiConfigUpdateForm (DriverBindingHandle
, ConfigFormEntry
->Controller
, FALSE
);
1085 // Remove HII package list
1087 mCallbackInfo
->HiiDatabase
->RemovePackageList (
1088 mCallbackInfo
->HiiDatabase
,
1089 mCallbackInfo
->RegisteredHandle
1093 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
1095 gBS
->UninstallMultipleProtocolInterfaces (
1096 mCallbackInfo
->DriverHandle
,
1097 &gEfiDevicePathProtocolGuid
,
1098 &mIScsiHiiVendorDevicePath
,
1099 &gEfiHiiConfigAccessProtocolGuid
,
1100 &mCallbackInfo
->ConfigAccess
,
1103 FreePool (mCallbackInfo
);