2 Helper functions for configuring or getting the parameters relating to iSCSI.
4 Copyright (c) 2004 - 2009, Intel Corporation.<BR>
5 All rights reserved. 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_SIMPLE_NETWORK_PROTOCOL
*Snp
;
88 EFI_SIMPLE_NETWORK_MODE
*Mode
;
89 ISCSI_MAC_INFO
*CurMacInfo
;
90 ISCSI_MAC_INFO TempMacInfo
;
95 // Dump all the handles the Simple Network Protocol is installed on.
97 Status
= gBS
->LocateHandleBuffer (
99 &gEfiSimpleNetworkProtocolGuid
,
104 if (EFI_ERROR (Status
)) {
109 Status
= gRT
->GetVariable (
116 if (Status
== EFI_BUFFER_TOO_SMALL
) {
117 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DataSize
);
129 for (HandleIndex
= 0; HandleIndex
< NumHandles
; HandleIndex
++) {
130 gBS
->HandleProtocol (Handles
[HandleIndex
], &gEfiSimpleNetworkProtocolGuid
, (VOID
**)&Snp
);
134 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
135 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
136 if ((CurMacInfo
->Len
== Mode
->HwAddressSize
) &&
137 (NET_MAC_EQUAL (&CurMacInfo
->Mac
, &Mode
->PermanentAddress
, Mode
->HwAddressSize
))
140 // The previous configured NIC is still here.
142 if (Index
!= LastDeviceIndex
) {
144 // Swap the current MAC address entry with the one indexed by
147 CopyMem (&TempMacInfo
, CurMacInfo
, sizeof (ISCSI_MAC_INFO
));
148 CopyMem (CurMacInfo
, &DeviceList
->MacInfo
[LastDeviceIndex
], sizeof (ISCSI_MAC_INFO
));
149 CopyMem (&DeviceList
->MacInfo
[LastDeviceIndex
], &TempMacInfo
, sizeof (ISCSI_MAC_INFO
));
156 if (LastDeviceIndex
== DeviceList
->NumDevice
) {
161 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
163 // delete the variables
165 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
166 IScsiMacAddrToStr (&CurMacInfo
->Mac
, CurMacInfo
->Len
, MacString
);
167 gRT
->SetVariable (MacString
, &gEfiIScsiInitiatorNameProtocolGuid
, 0, 0, NULL
);
168 gRT
->SetVariable (MacString
, &mIScsiCHAPAuthInfoGuid
, 0, 0, NULL
);
171 FreePool (DeviceList
);
172 } else if (Status
!= EFI_NOT_FOUND
) {
177 // Construct the new iSCSI device list.
179 DeviceListSize
= sizeof (ISCSI_DEVICE_LIST
) + (NumHandles
- 1) * sizeof (ISCSI_MAC_INFO
);
180 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DeviceListSize
);
181 DeviceList
->NumDevice
= (UINT8
) NumHandles
;
183 for (Index
= 0; Index
< NumHandles
; Index
++) {
184 gBS
->HandleProtocol (Handles
[Index
], &gEfiSimpleNetworkProtocolGuid
, (VOID
**)&Snp
);
187 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
188 CopyMem (&CurMacInfo
->Mac
, &Mode
->PermanentAddress
, Mode
->HwAddressSize
);
189 CurMacInfo
->Len
= (UINT8
) Mode
->HwAddressSize
;
195 ISCSI_CONFIG_VAR_ATTR
,
200 FreePool (DeviceList
);
207 Get the iSCSI configuration form entry by the index of the goto opcode actived.
209 @param[in] Index The 0-based index of the goto opcode actived.
211 @return The iSCSI configuration form entry found.
213 ISCSI_CONFIG_FORM_ENTRY
*
214 IScsiGetConfigFormEntryByIndex (
220 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
223 ConfigFormEntry
= NULL
;
225 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
226 if (CurrentIndex
== Index
) {
227 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
234 return ConfigFormEntry
;
238 Convert the iSCSI configuration data into the IFR data.
240 @param[in] ConfigFormEntry The iSCSI configuration form entry.
241 @param[out] IfrNvData The IFR nv data.
244 IScsiConvertDeviceConfigDataToIfrNvData (
245 IN ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
246 OUT ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
249 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
250 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
253 // Normal session configuration parameters.
255 SessionConfigData
= &ConfigFormEntry
->SessionConfigData
;
256 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
258 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
259 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
260 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
262 IScsiIpToStr (&SessionConfigData
->LocalIp
, IfrNvData
->LocalIp
);
263 IScsiIpToStr (&SessionConfigData
->SubnetMask
, IfrNvData
->SubnetMask
);
264 IScsiIpToStr (&SessionConfigData
->Gateway
, IfrNvData
->Gateway
);
265 IScsiIpToStr (&SessionConfigData
->TargetIp
, IfrNvData
->TargetIp
);
267 IScsiAsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
269 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
272 // CHAP authentication parameters.
274 AuthConfigData
= &ConfigFormEntry
->AuthConfigData
;
276 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
278 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
279 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
280 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
281 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
285 This function allows the caller to request the current
286 configuration for one or more named elements. The resulting
287 string is in <ConfigAltResp> format. Any and all alternative
288 configuration strings shall also be appended to the end of the
289 current configuration string. If they are, they must appear
290 after the current configuration. They must contain the same
291 routing (GUID, NAME, PATH) as the current configuration string.
292 They must have an additional description indicating the type of
293 alternative configuration the string represents,
294 "ALTCFG=<StringToken>". That <StringToken> (when
295 converted from Hex UNICODE to binary) is a reference to a
296 string in the associated string pack.
298 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
299 @param[in] Request A null-terminated Unicode string in
300 <ConfigRequest> format. Note that this
301 includes the routing information as well as
302 the configurable name / value pairs. It is
303 invalid for this string to be in
304 <MultiConfigRequest> format.
305 @param[out] Progress On return, points to a character in the
306 Request string. Points to the string's null
307 terminator if request was successful. Points
308 to the most recent "&" before the first
309 failing name / value pair (or the beginning
310 of the string if the failure is in the first
311 name / value pair) if the request was not
313 @param[out] Results A null-terminated Unicode string in
314 <ConfigAltResp> format which has all values
315 filled in for the names in the Request string.
316 String to be allocated by the called function.
318 @retval EFI_SUCCESS The Results string is filled with the
319 values corresponding to all requested
321 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
322 parts of the results that must be
323 stored awaiting possible future
325 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
326 for the Request parameter
327 would result in this type of
328 error. In this case, the
329 Progress parameter would be
331 @retval EFI_NOT_FOUND Routing data doesn't match any
332 known driver. Progress set to the
333 first character in the routing header.
334 Note: There is no requirement that the
335 driver validate the routing data. It
336 must skip the <ConfigHdr> in order to
338 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
339 to most recent & before the
340 error or the beginning of the
342 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
343 to the & before the name in
344 question.Currently not implemented.
348 IScsiFormExtractConfig (
349 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
350 IN CONST EFI_STRING Request
,
351 OUT EFI_STRING
*Progress
,
352 OUT EFI_STRING
*Results
356 CHAR8 InitiatorName
[ISCSI_NAME_IFR_MAX_SIZE
];
358 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
359 ISCSI_FORM_CALLBACK_INFO
*Private
;
360 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
362 if (Request
== NULL
|| Progress
== NULL
|| Results
== NULL
) {
363 return EFI_INVALID_PARAMETER
;
367 if (!mIScsiDeviceListUpdated
) {
369 // Update the device list.
371 IScsiUpdateDeviceList ();
372 mIScsiDeviceListUpdated
= TRUE
;
375 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
376 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
377 ASSERT (IfrNvData
!= NULL
);
378 if (Private
->Current
!= NULL
) {
379 IScsiConvertDeviceConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
382 BufferSize
= ISCSI_NAME_IFR_MAX_SIZE
;
383 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
384 if (EFI_ERROR (Status
)) {
385 IfrNvData
->InitiatorName
[0] = L
'\0';
387 IScsiAsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
391 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
393 HiiConfigRouting
= Private
->ConfigRouting
;
394 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
395 Status
= HiiConfigRouting
->BlockToConfig (
403 FreePool (IfrNvData
);
408 This function applies changes in a driver's configuration.
409 Input is a Configuration, which has the routing data for this
410 driver followed by name / value configuration pairs. The driver
411 must apply those pairs to its configurable storage. If the
412 driver's configuration is stored in a linear block of data
413 and the driver's name / value pairs are in <BlockConfig>
414 format, it may use the ConfigToBlock helper function (above) to
415 simplify the job. Currently not implemented.
417 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
418 @param[in] Configuration A null-terminated Unicode string in
419 <ConfigString> format.
420 @param[out] Progress A pointer to a string filled in with the
421 offset of the most recent '&' before the
422 first failing name / value pair (or the
423 beginn ing of the string if the failure
424 is in the first name / value pair) or
425 the terminating NULL if all was
428 @retval EFI_SUCCESS The results have been distributed or are
429 awaiting distribution.
430 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
431 parts of the results that must be
432 stored awaiting possible future
434 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
435 Results parameter would result
436 in this type of error.
437 @retval EFI_NOT_FOUND Target for the specified routing data
442 IScsiFormRouteConfig (
443 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
444 IN CONST EFI_STRING Configuration
,
445 OUT EFI_STRING
*Progress
448 if (Configuration
== NULL
|| Progress
== NULL
) {
449 return EFI_INVALID_PARAMETER
;
453 // Check routing data in <ConfigHdr>.
454 // Note: if only one Storage is used, then this checking could be skipped.
456 if (!HiiIsConfigHdrMatch (Configuration
, &mVendorGuid
, mVendorStorageName
)) {
457 *Progress
= Configuration
;
458 return EFI_NOT_FOUND
;
461 *Progress
= Configuration
+ StrLen (Configuration
);
466 This function is called to provide results data to the driver.
467 This data consists of a unique key that is used to identify
468 which data is either being passed back or being asked for.
470 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
471 @param[in] Action Specifies the type of action taken by the browser.
472 @param[in] QuestionId A unique value which is sent to the original
473 exporting driver so that it can identify the type
474 of data to expect. The format of the data tends to
475 vary based on the opcode that enerated the callback.
476 @param[in] Type The type of value for the question.
477 @param[in] Value A pointer to the data being sent to the original
479 @param[out] ActionRequest On return, points to the action requested by the
482 @retval EFI_SUCCESS The callback successfully handled the action.
483 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
484 variable and its data.
485 @retval EFI_DEVICE_ERROR The variable could not be saved.
486 @retval EFI_UNSUPPORTED The specified Action is not supported by the
487 callback.Currently not implemented.
488 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.
489 @retval Others Other errors as indicated.
494 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
495 IN EFI_BROWSER_ACTION Action
,
496 IN EFI_QUESTION_ID QuestionId
,
498 IN EFI_IFR_TYPE_VALUE
*Value
,
499 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
502 ISCSI_FORM_CALLBACK_INFO
*Private
;
504 CHAR8 IScsiName
[ISCSI_NAME_IFR_MAX_SIZE
];
505 CHAR16 PortString
[128];
506 CHAR8 Ip4String
[IP4_STR_MAX_SIZE
];
507 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
509 EFI_STRING_ID DeviceFormTitleToken
;
510 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
511 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
512 EFI_IP_ADDRESS HostIp
;
513 EFI_IP_ADDRESS SubnetMask
;
514 EFI_IP_ADDRESS Gateway
;
518 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
521 // Retrive uncommitted data from Browser
523 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
524 ASSERT (IfrNvData
!= NULL
);
525 if (!HiiGetBrowserData (&mVendorGuid
, mVendorStorageName
, sizeof (ISCSI_CONFIG_IFR_NVDATA
), (UINT8
*) IfrNvData
)) {
526 FreePool (IfrNvData
);
527 return EFI_NOT_FOUND
;
530 Status
= EFI_SUCCESS
;
532 switch (QuestionId
) {
533 case KEY_INITIATOR_NAME
:
534 IScsiUnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
535 BufferSize
= AsciiStrLen (IScsiName
) + 1;
537 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
538 if (EFI_ERROR (Status
)) {
539 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid iSCSI Name!", NULL
);
545 IScsiUnicodeStrToAsciiStr (IfrNvData
->LocalIp
, Ip4String
);
546 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
547 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
548 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid IP address!", NULL
);
549 Status
= EFI_INVALID_PARAMETER
;
551 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
556 case KEY_SUBNET_MASK
:
557 IScsiUnicodeStrToAsciiStr (IfrNvData
->SubnetMask
, Ip4String
);
558 Status
= IScsiAsciiStrToIp (Ip4String
, &SubnetMask
.v4
);
559 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
560 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid Subnet Mask!", NULL
);
561 Status
= EFI_INVALID_PARAMETER
;
563 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
569 IScsiUnicodeStrToAsciiStr (IfrNvData
->Gateway
, Ip4String
);
570 Status
= IScsiAsciiStrToIp (Ip4String
, &Gateway
.v4
);
571 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
572 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid Gateway!", NULL
);
573 Status
= EFI_INVALID_PARAMETER
;
575 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
581 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetIp
, Ip4String
);
582 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
583 if (EFI_ERROR (Status
) || !NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
584 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid IP address!", NULL
);
585 Status
= EFI_INVALID_PARAMETER
;
587 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
592 case KEY_TARGET_NAME
:
593 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
594 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
595 if (EFI_ERROR (Status
)) {
596 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid iSCSI Name!", NULL
);
598 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
603 case KEY_DHCP_ENABLE
:
604 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
605 IfrNvData
->TargetInfoFromDhcp
= 0;
611 IScsiUnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
612 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
613 if (EFI_ERROR (Status
)) {
614 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Invalid LUN string!", NULL
);
616 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
622 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPName
, Private
->Current
->AuthConfigData
.CHAPName
);
625 case KEY_CHAP_SECRET
:
626 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPSecret
, Private
->Current
->AuthConfigData
.CHAPSecret
);
629 case KEY_REVERSE_CHAP_NAME
:
630 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPName
, Private
->Current
->AuthConfigData
.ReverseCHAPName
);
633 case KEY_REVERSE_CHAP_SECRET
:
634 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPSecret
, Private
->Current
->AuthConfigData
.ReverseCHAPSecret
);
637 case KEY_SAVE_CHANGES
:
639 // First, update those fields which don't have INTERACTIVE set.
641 Private
->Current
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
642 Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
643 Private
->Current
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
644 if (Private
->Current
->SessionConfigData
.TargetPort
== 0) {
645 Private
->Current
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
648 Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
649 Private
->Current
->AuthConfigData
.CHAPType
= IfrNvData
->CHAPType
;
652 // Only do full parameter validation if iSCSI is enabled on this device.
654 if (Private
->Current
->SessionConfigData
.Enabled
) {
656 // Validate the address configuration of the Initiator if DHCP isn't
659 if (!Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
) {
660 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
661 CopyMem (&SubnetMask
.v4
, &Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
662 CopyMem (&Gateway
.v4
, &Private
->Current
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
664 if ((Gateway
.Addr
[0] != 0)) {
665 if (SubnetMask
.Addr
[0] == 0) {
666 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Gateway address is set but subnet mask is zero.", NULL
);
667 Status
= EFI_INVALID_PARAMETER
;
669 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
670 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Local IP and Gateway are not in the same subnet.", NULL
);
671 Status
= EFI_INVALID_PARAMETER
;
677 // Validate target configuration if DHCP isn't deployed.
679 if (!Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
) {
680 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.TargetIp
, sizeof (HostIp
.v4
));
681 if (!NetIp4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
682 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Target IP is invalid!", NULL
);
683 Status
= EFI_INVALID_PARAMETER
;
688 if (IfrNvData
->CHAPType
!= ISCSI_CHAP_NONE
) {
689 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
690 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"CHAP Name or CHAP Secret is invalid!", NULL
);
691 Status
= EFI_INVALID_PARAMETER
;
695 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
696 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
698 CreatePopUp (EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
, &Key
, L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!", NULL
);
699 Status
= EFI_INVALID_PARAMETER
;
705 BufferSize
= sizeof (Private
->Current
->SessionConfigData
);
707 Private
->Current
->MacString
,
708 &gEfiIScsiInitiatorNameProtocolGuid
,
709 ISCSI_CONFIG_VAR_ATTR
,
711 &Private
->Current
->SessionConfigData
714 BufferSize
= sizeof (Private
->Current
->AuthConfigData
);
716 Private
->Current
->MacString
,
717 &mIScsiCHAPAuthInfoGuid
,
718 ISCSI_CONFIG_VAR_ATTR
,
720 &Private
->Current
->AuthConfigData
722 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
726 if ((QuestionId
>= KEY_DEVICE_ENTRY_BASE
) && (QuestionId
< (mNumberOfIScsiDevices
+ KEY_DEVICE_ENTRY_BASE
))) {
728 // In case goto the device configuration form, update the device form title.
730 ConfigFormEntry
= IScsiGetConfigFormEntryByIndex ((UINT32
) (QuestionId
- KEY_DEVICE_ENTRY_BASE
));
731 ASSERT (ConfigFormEntry
!= NULL
);
733 UnicodeSPrint (PortString
, (UINTN
) 128, L
"Port %s", ConfigFormEntry
->MacString
);
734 DeviceFormTitleToken
= (EFI_STRING_ID
) STR_ISCSI_DEVICE_FORM_TITLE
;
735 HiiSetString (Private
->RegisteredHandle
, DeviceFormTitleToken
, PortString
, NULL
);
737 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry
, IfrNvData
);
739 Private
->Current
= ConfigFormEntry
;
745 if (!EFI_ERROR (Status
)) {
747 // Pass changed uncommitted data back to Form Browser
749 HiiSetBrowserData (&mVendorGuid
, mVendorStorageName
, sizeof (ISCSI_CONFIG_IFR_NVDATA
), (UINT8
*) IfrNvData
, NULL
);
752 FreePool (IfrNvData
);
757 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
758 device specified by the Controller.
760 @param[in] DriverBindingHandle The driverbinding handle.
761 @param[in] Controller The controller handle of the iSCSI device.
762 @param[in] AddForm Whether to add or delete a form entry.
764 @retval EFI_SUCCESS The iSCSI configuration form is updated.
765 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
766 @retval Others Other errors as indicated.
769 IScsiConfigUpdateForm (
770 IN EFI_HANDLE DriverBindingHandle
,
771 IN EFI_HANDLE Controller
,
776 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
777 BOOLEAN EntryExisted
;
779 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
780 CHAR16 PortString
[128];
783 VOID
*StartOpCodeHandle
;
784 VOID
*EndOpCodeHandle
;
785 EFI_IFR_GUID_LABEL
*StartLabel
;
786 EFI_IFR_GUID_LABEL
*EndLabel
;
788 ConfigFormEntry
= NULL
;
789 EntryExisted
= FALSE
;
791 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
792 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
794 if (ConfigFormEntry
->Controller
== Controller
) {
807 ConfigFormEntry
= (ISCSI_CONFIG_FORM_ENTRY
*) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY
));
808 if (ConfigFormEntry
== NULL
) {
809 return EFI_OUT_OF_RESOURCES
;
812 InitializeListHead (&ConfigFormEntry
->Link
);
813 ConfigFormEntry
->Controller
= Controller
;
816 // Get the simple network protocol and convert the MAC address into
817 // the formatted string.
819 Status
= gBS
->HandleProtocol (
821 &gEfiSimpleNetworkProtocolGuid
,
824 ASSERT (Status
== EFI_SUCCESS
);
826 IScsiMacAddrToStr (&Snp
->Mode
->PermanentAddress
, Snp
->Mode
->HwAddressSize
, ConfigFormEntry
->MacString
);
829 // Get the normal session configuration data.
831 BufferSize
= sizeof (ConfigFormEntry
->SessionConfigData
);
832 Status
= gRT
->GetVariable (
833 ConfigFormEntry
->MacString
,
834 &gEfiIScsiInitiatorNameProtocolGuid
,
837 &ConfigFormEntry
->SessionConfigData
839 if (EFI_ERROR (Status
)) {
840 ZeroMem (&ConfigFormEntry
->SessionConfigData
, sizeof (ConfigFormEntry
->SessionConfigData
));
843 // Get the CHAP authentication configuration data.
845 BufferSize
= sizeof (ConfigFormEntry
->AuthConfigData
);
846 Status
= gRT
->GetVariable (
847 ConfigFormEntry
->MacString
,
848 &mIScsiCHAPAuthInfoGuid
,
851 &ConfigFormEntry
->AuthConfigData
853 if (EFI_ERROR (Status
)) {
854 ZeroMem (&ConfigFormEntry
->AuthConfigData
, sizeof (ConfigFormEntry
->AuthConfigData
));
857 // Compose the Port string and create a new EFI_STRING_ID.
859 UnicodeSPrint (PortString
, 128, L
"Port %s", ConfigFormEntry
->MacString
);
860 ConfigFormEntry
->PortTitleToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, PortString
, NULL
);
863 // Compose the help string of this port and create a new EFI_STRING_ID.
865 UnicodeSPrint (PortString
, 128, L
"Set the iSCSI parameters on port %s", ConfigFormEntry
->MacString
);
866 ConfigFormEntry
->PortTitleHelpToken
= HiiSetString (mCallbackInfo
->RegisteredHandle
, 0, PortString
, NULL
);
868 InsertTailList (&mIScsiConfigFormList
, &ConfigFormEntry
->Link
);
869 mNumberOfIScsiDevices
++;
872 ASSERT (EntryExisted
);
874 mNumberOfIScsiDevices
--;
875 RemoveEntryList (&ConfigFormEntry
->Link
);
876 FreePool (ConfigFormEntry
);
879 // Allocate space for creation of Buffer
883 // Init OpCode Handle
885 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
886 ASSERT (StartOpCodeHandle
!= NULL
);
888 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
889 ASSERT (EndOpCodeHandle
!= NULL
);
892 // Create Hii Extend Label OpCode as the start opcode
894 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (StartOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
895 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
896 StartLabel
->Number
= DEVICE_ENTRY_LABEL
;
899 // Create Hii Extend Label OpCode as the end opcode
901 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (EndOpCodeHandle
, &gEfiIfrTianoGuid
, NULL
, sizeof (EFI_IFR_GUID_LABEL
));
902 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
903 EndLabel
->Number
= LABEL_END
;
906 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
907 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
909 HiiCreateGotoOpCode (
910 StartOpCodeHandle
, // Container for dynamic created opcodes
911 FORMID_DEVICE_FORM
, // Target Form ID
912 ConfigFormEntry
->PortTitleToken
, // Prompt text
913 ConfigFormEntry
->PortTitleHelpToken
, // Help text
914 EFI_IFR_FLAG_CALLBACK
, // Question flag
915 (UINT16
)(KEY_DEVICE_ENTRY_BASE
+ FormIndex
) // Question ID
922 mCallbackInfo
->RegisteredHandle
,
925 StartOpCodeHandle
, // Label DEVICE_ENTRY_LABEL
926 EndOpCodeHandle
// LABEL_END
929 HiiFreeOpCodeHandle (StartOpCodeHandle
);
930 HiiFreeOpCodeHandle (EndOpCodeHandle
);
936 Initialize the iSCSI configuration form.
938 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
940 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
941 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
942 @retval Others Other errors as indicated.
945 IScsiConfigFormInit (
950 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
951 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
953 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**)&HiiDatabase
);
954 if (EFI_ERROR (Status
)) {
958 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
959 if (CallbackInfo
== NULL
) {
960 return EFI_OUT_OF_RESOURCES
;
963 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
964 CallbackInfo
->HiiDatabase
= HiiDatabase
;
965 CallbackInfo
->Current
= NULL
;
967 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
968 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
969 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
971 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**)&CallbackInfo
->ConfigRouting
);
972 if (EFI_ERROR (Status
)) {
973 FreePool(CallbackInfo
);
978 // Install Device Path Protocol and Config Access protocol to driver handle
980 Status
= gBS
->InstallMultipleProtocolInterfaces (
981 &CallbackInfo
->DriverHandle
,
982 &gEfiDevicePathProtocolGuid
,
983 &mIScsiHiiVendorDevicePath
,
984 &gEfiHiiConfigAccessProtocolGuid
,
985 &CallbackInfo
->ConfigAccess
,
988 ASSERT_EFI_ERROR (Status
);
991 // Publish our HII data
993 CallbackInfo
->RegisteredHandle
= HiiAddPackages (
995 CallbackInfo
->DriverHandle
,
1000 if (CallbackInfo
->RegisteredHandle
== NULL
) {
1001 FreePool(CallbackInfo
);
1002 return EFI_OUT_OF_RESOURCES
;
1005 mCallbackInfo
= CallbackInfo
;
1011 Unload the iSCSI configuration form, this includes: delete all the iSCSI
1012 device configuration entries, uninstall the form callback protocol and
1013 free the resources used.
1015 @param[in] DriverBindingHandle The iSCSI driverbinding handle.
1017 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
1018 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1021 IScsiConfigFormUnload (
1022 IN EFI_HANDLE DriverBindingHandle
1025 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
1027 while (!IsListEmpty (&mIScsiConfigFormList
)) {
1029 // Uninstall the device forms as the iSCSI driver instance may fail to
1030 // control the controller but still install the device configuration form.
1031 // In such case, upon driver unloading, the driver instance's driverbinding.
1032 // stop () won't be called, so we have to take this chance here to uninstall
1035 ConfigFormEntry
= NET_LIST_USER_STRUCT (mIScsiConfigFormList
.ForwardLink
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
1036 IScsiConfigUpdateForm (DriverBindingHandle
, ConfigFormEntry
->Controller
, FALSE
);
1040 // Remove HII package list
1042 mCallbackInfo
->HiiDatabase
->RemovePackageList (
1043 mCallbackInfo
->HiiDatabase
,
1044 mCallbackInfo
->RegisteredHandle
1048 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
1050 gBS
->UninstallMultipleProtocolInterfaces (
1051 mCallbackInfo
->DriverHandle
,
1052 &gEfiDevicePathProtocolGuid
,
1053 &mIScsiHiiVendorDevicePath
,
1054 &gEfiHiiConfigAccessProtocolGuid
,
1055 &mCallbackInfo
->ConfigAccess
,
1058 FreePool (mCallbackInfo
);