2 Helper functions for configuring or getting the parameters relating to ISCSI
4 Copyright (c) 2004 - 2008, Intel Corporation
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.
19 Helper functions for configuring or getting the parameters relating to ISCSI
23 #include "IScsiImpl.h"
25 EFI_GUID mVendorGuid
= ISCSI_CONFIG_GUID
;
26 BOOLEAN mIScsiDeviceListUpdated
= FALSE
;
27 UINTN mNumberOfIScsiDevices
= 0;
28 ISCSI_FORM_CALLBACK_INFO
*mCallbackInfo
= NULL
;
30 LIST_ENTRY mIScsiConfigFormList
= {
31 &mIScsiConfigFormList
,
36 Convert the IPv4 address into a dotted string.
38 @param Ip[in] The IPv4 address.
40 @param Str[out] The dotted IP string.
48 IN EFI_IPv4_ADDRESS
*Ip
,
52 UnicodeSPrint ( Str
, 2 * IP4_STR_MAX_SIZE
, L
"%d.%d.%d.%d", Ip
->Addr
[0], Ip
->Addr
[1], Ip
->Addr
[2], Ip
->Addr
[3]);
56 Pop up an invalid notify which displays the message in Warning.
58 @param Warning[in] The warning message.
70 IfrLibCreatePopUp (1, &Key
, Warning
);
74 Update the list of iSCSI devices the iSCSI driver is controlling.
82 IScsiUpdateDeviceList (
87 ISCSI_DEVICE_LIST
*DeviceList
;
93 UINTN LastDeviceIndex
;
94 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
95 EFI_SIMPLE_NETWORK_MODE
*Mode
;
96 ISCSI_MAC_INFO
*CurMacInfo
;
97 ISCSI_MAC_INFO TempMacInfo
;
102 // Dump all the handles the Simple Network Protocol is installed on.
104 Status
= gBS
->LocateHandleBuffer (
106 &gEfiSimpleNetworkProtocolGuid
,
111 if (EFI_ERROR (Status
)) {
116 Status
= gRT
->GetVariable (
123 if (Status
== EFI_BUFFER_TOO_SMALL
) {
124 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DataSize
);
136 for (HandleIndex
= 0; HandleIndex
< NumHandles
; HandleIndex
++) {
137 gBS
->HandleProtocol (Handles
[HandleIndex
], &gEfiSimpleNetworkProtocolGuid
, (VOID
**)&Snp
);
141 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
142 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
143 if ((CurMacInfo
->Len
== Mode
->HwAddressSize
) &&
144 (NET_MAC_EQUAL (&CurMacInfo
->Mac
, &Mode
->PermanentAddress
, Mode
->HwAddressSize
))
147 // The previous configured NIC is still here.
149 if (Index
!= LastDeviceIndex
) {
151 // Swap the current MAC address entry with the one indexed by
154 CopyMem (&TempMacInfo
, CurMacInfo
, sizeof (ISCSI_MAC_INFO
));
155 CopyMem (CurMacInfo
, &DeviceList
->MacInfo
[LastDeviceIndex
], sizeof (ISCSI_MAC_INFO
));
156 CopyMem (&DeviceList
->MacInfo
[LastDeviceIndex
], &TempMacInfo
, sizeof (ISCSI_MAC_INFO
));
163 if (LastDeviceIndex
== DeviceList
->NumDevice
) {
168 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
170 // delete the variables
172 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
173 IScsiMacAddrToStr (&CurMacInfo
->Mac
, CurMacInfo
->Len
, MacString
);
174 gRT
->SetVariable (MacString
, &gEfiIScsiInitiatorNameProtocolGuid
, 0, 0, NULL
);
175 gRT
->SetVariable (MacString
, &mIScsiCHAPAuthInfoGuid
, 0, 0, NULL
);
178 gBS
->FreePool (DeviceList
);
179 } else if (Status
!= EFI_NOT_FOUND
) {
180 gBS
->FreePool (Handles
);
184 // Construct the new iSCSI device list.
186 DeviceListSize
= sizeof (ISCSI_DEVICE_LIST
) + (NumHandles
- 1) * sizeof (ISCSI_MAC_INFO
);
187 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DeviceListSize
);
188 DeviceList
->NumDevice
= (UINT8
) NumHandles
;
190 for (Index
= 0; Index
< NumHandles
; Index
++) {
191 gBS
->HandleProtocol (Handles
[Index
], &gEfiSimpleNetworkProtocolGuid
, (VOID
**)&Snp
);
194 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
195 CopyMem (&CurMacInfo
->Mac
, &Mode
->PermanentAddress
, Mode
->HwAddressSize
);
196 CurMacInfo
->Len
= (UINT8
) Mode
->HwAddressSize
;
202 ISCSI_CONFIG_VAR_ATTR
,
207 gBS
->FreePool (DeviceList
);
208 gBS
->FreePool (Handles
);
214 Get the iSCSI configuration form entry by the index of the goto opcode actived.
216 @param Index[in] The 0-based index of the goto opcode actived.
218 @retval The iSCSI configuration form entry found.
222 ISCSI_CONFIG_FORM_ENTRY
*
223 IScsiGetConfigFormEntryByIndex (
229 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
232 ConfigFormEntry
= NULL
;
234 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
235 if (CurrentIndex
== Index
) {
236 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
243 return ConfigFormEntry
;
247 Convert the iSCSI configuration data into the IFR data.
249 @param ConfigFormEntry[in] The iSCSI configuration form entry.
251 @param IfrNvData[in] The IFR nv data.
258 IScsiConvertDeviceConfigDataToIfrNvData (
259 IN ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
260 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
263 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
264 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
267 // Normal session configuration parameters.
269 SessionConfigData
= &ConfigFormEntry
->SessionConfigData
;
270 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
272 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
273 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
274 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
276 IScsiIpToStr (&SessionConfigData
->LocalIp
, IfrNvData
->LocalIp
);
277 IScsiIpToStr (&SessionConfigData
->SubnetMask
, IfrNvData
->SubnetMask
);
278 IScsiIpToStr (&SessionConfigData
->Gateway
, IfrNvData
->Gateway
);
279 IScsiIpToStr (&SessionConfigData
->TargetIp
, IfrNvData
->TargetIp
);
281 IScsiAsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
283 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
286 // CHAP authentication parameters.
288 AuthConfigData
= &ConfigFormEntry
->AuthConfigData
;
290 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
292 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
293 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
294 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
295 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
299 This function allows a caller to extract the current configuration for one
300 or more named elements from the target driver.
302 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
304 @param Request[in] A null-terminated Unicode string in <ConfigRequest> format.
306 @param Progress[out] On return, points to a character in the Request string.
307 Points to the string's null terminator if request was successful.
308 Points to the most recent '&' before the first failing name/value
309 pair (or the beginning of the string if the failure is in the
310 first name/value pair) if the request was not successful.
312 @param Results[out] A null-terminated Unicode string in <ConfigAltResp> format which
313 has all values filled in for the names in the Request string.
314 String to be allocated by the called function.
316 @retval EFI_SUCCESS The Results is filled with the requested values.
318 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
320 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
322 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
327 IScsiFormExtractConfig (
328 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
329 IN CONST EFI_STRING Request
,
330 OUT EFI_STRING
*Progress
,
331 OUT EFI_STRING
*Results
335 CHAR8 InitiatorName
[ISCSI_NAME_IFR_MAX_SIZE
];
337 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
338 ISCSI_FORM_CALLBACK_INFO
*Private
;
339 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
341 if (!mIScsiDeviceListUpdated
) {
343 // Update the device list.
345 IScsiUpdateDeviceList ();
346 mIScsiDeviceListUpdated
= TRUE
;
349 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
350 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
351 ASSERT (IfrNvData
!= NULL
);
352 if (Private
->Current
!= NULL
) {
353 IScsiConvertDeviceConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
356 BufferSize
= ISCSI_NAME_IFR_MAX_SIZE
;
357 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
358 if (EFI_ERROR (Status
)) {
359 IfrNvData
->InitiatorName
[0] = L
'\0';
361 IScsiAsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
365 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
367 HiiConfigRouting
= Private
->ConfigRouting
;
368 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
369 Status
= HiiConfigRouting
->BlockToConfig (
377 gBS
->FreePool (IfrNvData
);
382 This function processes the results of changes in configuration.
384 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
386 @param Configuration[in] A null-terminated Unicode string in <ConfigResp> format.
388 @param Progress[out] A pointer to a string filled in with the offset of the most
389 recent '&' before the first failing name/value pair (or the
390 beginning of the string if the failure is in the first
391 name/value pair) or the terminating NULL if all was successful.
393 @retval EFI_SUCCESS The Results is processed successfully.
395 @retval EFI_INVALID_PARAMETER Configuration is NULL.
397 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
402 IScsiFormRouteConfig (
403 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
404 IN CONST EFI_STRING Configuration
,
405 OUT EFI_STRING
*Progress
412 This function processes the results of changes in configuration.
414 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
416 @param Action[in] Specifies the type of action taken by the browser.
418 @param QuestionId[in] A unique value which is sent to the original exporting driver
419 so that it can identify the type of data to expect.
421 @param Type[in] The type of value for the question.
423 @param Value[in] A pointer to the data being sent to the original exporting driver.
425 @param ActionRequest[out] On return, points to the action requested by the callback function.
427 @retval EFI_SUCCESS The callback successfully handled the action.
429 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
431 @retval EFI_DEVICE_ERROR The variable could not be saved.
433 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
439 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
440 IN EFI_BROWSER_ACTION Action
,
441 IN EFI_QUESTION_ID KeyValue
,
443 IN EFI_IFR_TYPE_VALUE
*Value
,
444 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
447 ISCSI_FORM_CALLBACK_INFO
*Private
;
449 CHAR8 IScsiName
[ISCSI_NAME_IFR_MAX_SIZE
];
450 CHAR16 PortString
[128];
451 CHAR8 Ip4String
[IP4_STR_MAX_SIZE
];
452 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
454 STRING_REF DeviceFormTitleToken
;
455 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
456 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
457 EFI_IP_ADDRESS HostIp
;
458 EFI_IP_ADDRESS SubnetMask
;
459 EFI_IP_ADDRESS Gateway
;
462 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
465 // Retrive uncommitted data from Browser
467 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
468 IfrNvData
= AllocateZeroPool (BufferSize
);
469 ASSERT (IfrNvData
!= NULL
);
470 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) IfrNvData
);
471 if (EFI_ERROR (Status
)) {
472 gBS
->FreePool (IfrNvData
);
477 case KEY_INITIATOR_NAME
:
478 IScsiUnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
479 BufferSize
= AsciiStrLen (IScsiName
) + 1;
481 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
482 if (EFI_ERROR (Status
)) {
483 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
489 IScsiUnicodeStrToAsciiStr (IfrNvData
->LocalIp
, Ip4String
);
490 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
491 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
492 PopUpInvalidNotify (L
"Invalid IP address!");
493 Status
= EFI_INVALID_PARAMETER
;
495 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
500 case KEY_SUBNET_MASK
:
501 IScsiUnicodeStrToAsciiStr (IfrNvData
->SubnetMask
, Ip4String
);
502 Status
= IScsiAsciiStrToIp (Ip4String
, &SubnetMask
.v4
);
503 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
504 PopUpInvalidNotify (L
"Invalid Subnet Mask!");
505 Status
= EFI_INVALID_PARAMETER
;
507 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
513 IScsiUnicodeStrToAsciiStr (IfrNvData
->Gateway
, Ip4String
);
514 Status
= IScsiAsciiStrToIp (Ip4String
, &Gateway
.v4
);
515 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
516 PopUpInvalidNotify (L
"Invalid Gateway!");
517 Status
= EFI_INVALID_PARAMETER
;
519 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
525 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetIp
, Ip4String
);
526 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
527 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
528 PopUpInvalidNotify (L
"Invalid IP address!");
529 Status
= EFI_INVALID_PARAMETER
;
531 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
536 case KEY_TARGET_NAME
:
537 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
538 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
539 if (EFI_ERROR (Status
)) {
540 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
542 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
547 case KEY_DHCP_ENABLE
:
548 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
549 IfrNvData
->TargetInfoFromDhcp
= 0;
555 IScsiUnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
556 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
557 if (EFI_ERROR (Status
)) {
558 PopUpInvalidNotify (L
"Invalid LUN string!");
560 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
566 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPName
, Private
->Current
->AuthConfigData
.CHAPName
);
569 case KEY_CHAP_SECRET
:
570 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPSecret
, Private
->Current
->AuthConfigData
.CHAPSecret
);
573 case KEY_REVERSE_CHAP_NAME
:
574 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPName
, Private
->Current
->AuthConfigData
.ReverseCHAPName
);
577 case KEY_REVERSE_CHAP_SECRET
:
578 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPSecret
, Private
->Current
->AuthConfigData
.ReverseCHAPSecret
);
581 case KEY_SAVE_CHANGES
:
583 // First, update those fields which don't have INTERACTIVE set.
585 Private
->Current
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
586 Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
587 Private
->Current
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
588 if (Private
->Current
->SessionConfigData
.TargetPort
== 0) {
589 Private
->Current
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
592 Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
593 Private
->Current
->AuthConfigData
.CHAPType
= IfrNvData
->CHAPType
;
596 // Only do full parameter validation if iSCSI is enabled on this device.
598 if (Private
->Current
->SessionConfigData
.Enabled
) {
600 // Validate the address configuration of the Initiator if DHCP isn't
603 if (!Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
) {
604 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
605 CopyMem (&SubnetMask
.v4
, &Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
606 CopyMem (&Gateway
.v4
, &Private
->Current
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
608 if ((Gateway
.Addr
[0] != 0)) {
609 if (SubnetMask
.Addr
[0] == 0) {
610 PopUpInvalidNotify (L
"Gateway address is set but subnet mask is zero.");
611 Status
= EFI_INVALID_PARAMETER
;
613 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
614 PopUpInvalidNotify (L
"Local IP and Gateway are not in the same subnet.");
615 Status
= EFI_INVALID_PARAMETER
;
621 // Validate target configuration if DHCP isn't deployed.
623 if (!Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
) {
624 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.TargetIp
, sizeof (HostIp
.v4
));
625 if (!Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
626 PopUpInvalidNotify (L
"Target IP is invalid!");
627 Status
= EFI_INVALID_PARAMETER
;
632 if (IfrNvData
->CHAPType
!= ISCSI_CHAP_NONE
) {
633 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
634 PopUpInvalidNotify (L
"CHAP Name or CHAP Secret is invalid!");
635 Status
= EFI_INVALID_PARAMETER
;
639 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
640 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
642 PopUpInvalidNotify (L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!");
643 Status
= EFI_INVALID_PARAMETER
;
649 BufferSize
= sizeof (Private
->Current
->SessionConfigData
);
651 Private
->Current
->MacString
,
652 &gEfiIScsiInitiatorNameProtocolGuid
,
653 ISCSI_CONFIG_VAR_ATTR
,
655 &Private
->Current
->SessionConfigData
658 BufferSize
= sizeof (Private
->Current
->AuthConfigData
);
660 Private
->Current
->MacString
,
661 &mIScsiCHAPAuthInfoGuid
,
662 ISCSI_CONFIG_VAR_ATTR
,
664 &Private
->Current
->AuthConfigData
666 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
670 if ((KeyValue
>= KEY_DEVICE_ENTRY_BASE
) && (KeyValue
< (mNumberOfIScsiDevices
+ KEY_DEVICE_ENTRY_BASE
))) {
672 // In case goto the device configuration form, update the device form title.
674 ConfigFormEntry
= IScsiGetConfigFormEntryByIndex ((UINT32
) (KeyValue
- KEY_DEVICE_ENTRY_BASE
));
675 ASSERT (ConfigFormEntry
!= NULL
);
677 UnicodeSPrint (PortString
, (UINTN
) 128, L
"Port %s", ConfigFormEntry
->MacString
);
678 DeviceFormTitleToken
= (STRING_REF
) STR_ISCSI_DEVICE_FORM_TITLE
;
679 HiiLibSetString (Private
->RegisteredHandle
, DeviceFormTitleToken
, PortString
);
681 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry
, IfrNvData
);
683 Private
->Current
= ConfigFormEntry
;
689 if (!EFI_ERROR (Status
)) {
691 // Pass changed uncommitted data back to Form Browser
693 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
694 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
697 gBS
->FreePool (IfrNvData
);
702 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
703 device specified by the Controller.
705 @param DriverBindingHandle[in] The driverbinding handle.
707 @param Controller[in] The controller handle of the iSCSI device.
709 @param AddForm[in] Whether to add or delete a form entry.
711 @retval EFI_SUCCESS The iSCSI configuration form is updated.
713 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
717 IScsiConfigUpdateForm (
718 IN EFI_HANDLE DriverBindingHandle
,
719 IN EFI_HANDLE Controller
,
724 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
725 BOOLEAN EntryExisted
;
727 EFI_HII_UPDATE_DATA UpdateData
;
728 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
729 CHAR16 PortString
[128];
734 ConfigFormEntry
= NULL
;
735 EntryExisted
= FALSE
;
737 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
738 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
740 if (ConfigFormEntry
->Controller
== Controller
) {
753 ConfigFormEntry
= (ISCSI_CONFIG_FORM_ENTRY
*) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY
));
754 if (ConfigFormEntry
== NULL
) {
755 return EFI_OUT_OF_RESOURCES
;
758 InitializeListHead (&ConfigFormEntry
->Link
);
759 ConfigFormEntry
->Controller
= Controller
;
762 // Get the simple network protocol and convert the MAC address into
763 // the formatted string.
765 Status
= gBS
->HandleProtocol (
767 &gEfiSimpleNetworkProtocolGuid
,
770 ASSERT (Status
== EFI_SUCCESS
);
772 IScsiMacAddrToStr (&Snp
->Mode
->PermanentAddress
, Snp
->Mode
->HwAddressSize
, ConfigFormEntry
->MacString
);
775 // Get the normal session configuration data.
777 BufferSize
= sizeof (ConfigFormEntry
->SessionConfigData
);
778 Status
= gRT
->GetVariable (
779 ConfigFormEntry
->MacString
,
780 &gEfiIScsiInitiatorNameProtocolGuid
,
783 &ConfigFormEntry
->SessionConfigData
785 if (EFI_ERROR (Status
)) {
786 ZeroMem (&ConfigFormEntry
->SessionConfigData
, sizeof (ConfigFormEntry
->SessionConfigData
));
789 // Get the CHAP authentication configuration data.
791 BufferSize
= sizeof (ConfigFormEntry
->AuthConfigData
);
792 Status
= gRT
->GetVariable (
793 ConfigFormEntry
->MacString
,
794 &mIScsiCHAPAuthInfoGuid
,
797 &ConfigFormEntry
->AuthConfigData
799 if (EFI_ERROR (Status
)) {
800 ZeroMem (&ConfigFormEntry
->AuthConfigData
, sizeof (ConfigFormEntry
->AuthConfigData
));
803 // Compose the Port string and create a new STRING_REF.
805 UnicodeSPrint (PortString
, 128, L
"Port %s", ConfigFormEntry
->MacString
);
806 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleToken
, PortString
);
809 // Compose the help string of this port and create a new STRING_REF.
811 UnicodeSPrint (PortString
, 128, L
"Set the iSCSI parameters on port %s", ConfigFormEntry
->MacString
);
812 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleHelpToken
, PortString
);
814 InsertTailList (&mIScsiConfigFormList
, &ConfigFormEntry
->Link
);
815 mNumberOfIScsiDevices
++;
818 ASSERT (EntryExisted
);
820 mNumberOfIScsiDevices
--;
821 RemoveEntryList (&ConfigFormEntry
->Link
);
822 gBS
->FreePool (ConfigFormEntry
);
825 // Allocate space for creation of Buffer
827 UpdateData
.BufferSize
= 0x1000;
828 UpdateData
.Data
= AllocateZeroPool (0x1000);
829 UpdateData
.Offset
= 0;
832 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
833 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
837 ConfigFormEntry
->PortTitleToken
,
838 ConfigFormEntry
->PortTitleHelpToken
,
839 EFI_IFR_FLAG_CALLBACK
,
840 (UINT16
)(KEY_DEVICE_ENTRY_BASE
+ FormIndex
),
848 mCallbackInfo
->RegisteredHandle
,
856 gBS
->FreePool (UpdateData
.Data
);
862 Initialize the iSCSI configuration form.
864 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
866 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
868 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
872 IScsiConfigFormInit (
873 IN EFI_HANDLE DriverBindingHandle
877 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
878 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
879 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
881 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**)&HiiDatabase
);
882 if (EFI_ERROR (Status
)) {
886 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
887 if (CallbackInfo
== NULL
) {
888 return EFI_OUT_OF_RESOURCES
;
891 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
892 CallbackInfo
->HiiDatabase
= HiiDatabase
;
893 CallbackInfo
->Current
= NULL
;
895 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
896 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
897 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
899 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**)&CallbackInfo
->ConfigRouting
);
900 if (EFI_ERROR (Status
)) {
901 FreePool(CallbackInfo
);
906 // Create driver handle used by HII database
908 Status
= HiiLibCreateHiiDriverHandle (&CallbackInfo
->DriverHandle
);
909 if (EFI_ERROR (Status
)) {
910 FreePool(CallbackInfo
);
915 // Install Config Access protocol to driver handle
917 Status
= gBS
->InstallProtocolInterface (
918 &CallbackInfo
->DriverHandle
,
919 &gEfiHiiConfigAccessProtocolGuid
,
920 EFI_NATIVE_INTERFACE
,
921 &CallbackInfo
->ConfigAccess
923 ASSERT_EFI_ERROR (Status
);
926 // Publish our HII data
928 PackageList
= HiiLibPreparePackageList (2, &mVendorGuid
, IScsiDxeStrings
, IScsiConfigDxeBin
);
929 ASSERT (PackageList
!= NULL
);
931 Status
= HiiDatabase
->NewPackageList (
934 CallbackInfo
->DriverHandle
,
935 &CallbackInfo
->RegisteredHandle
937 FreePool (PackageList
);
938 if (EFI_ERROR (Status
)) {
939 FreePool(CallbackInfo
);
943 mCallbackInfo
= CallbackInfo
;
949 Unload the iSCSI configuration form, this includes: delete all the iSCSI
950 device configuration entries, uninstall the form callback protocol and
951 free the resources used.
953 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
955 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
957 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
961 IScsiConfigFormUnload (
962 IN EFI_HANDLE DriverBindingHandle
965 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
967 while (!IsListEmpty (&mIScsiConfigFormList
)) {
969 // Uninstall the device forms as the iSCSI driver instance may fail to
970 // control the controller but still install the device configuration form.
971 // In such case, upon driver unloading, the driver instance's driverbinding.
972 // stop () won't be called, so we have to take this chance here to uninstall
975 ConfigFormEntry
= NET_LIST_USER_STRUCT (mIScsiConfigFormList
.ForwardLink
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
976 IScsiConfigUpdateForm (DriverBindingHandle
, ConfigFormEntry
->Controller
, FALSE
);
980 // Remove HII package list
982 mCallbackInfo
->HiiDatabase
->RemovePackageList (
983 mCallbackInfo
->HiiDatabase
,
984 mCallbackInfo
->RegisteredHandle
988 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
990 gBS
->UninstallProtocolInterface (
991 mCallbackInfo
->DriverHandle
,
992 &gEfiHiiConfigAccessProtocolGuid
,
993 &mCallbackInfo
->ConfigAccess
995 HiiLibDestroyHiiDriverHandle (mCallbackInfo
->DriverHandle
);
997 gBS
->FreePool (mCallbackInfo
);