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
);
213 Get the iSCSI configuration form entry by the index of the goto opcode actived.
215 @param Index[in] The 0-based index of the goto opcode actived.
217 @retval The iSCSI configuration form entry found.
221 ISCSI_CONFIG_FORM_ENTRY
*
222 IScsiGetConfigFormEntryByIndex (
228 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
231 ConfigFormEntry
= NULL
;
233 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
234 if (CurrentIndex
== Index
) {
235 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
242 return ConfigFormEntry
;
246 Convert the iSCSI configuration data into the IFR data.
248 @param ConfigFormEntry[in] The iSCSI configuration form entry.
250 @param IfrNvData[in] The IFR nv data.
257 IScsiConvertDeviceConfigDataToIfrNvData (
258 IN ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
259 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
262 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
263 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
266 // Normal session configuration parameters.
268 SessionConfigData
= &ConfigFormEntry
->SessionConfigData
;
269 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
271 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
272 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
273 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
275 IScsiIpToStr (&SessionConfigData
->LocalIp
, IfrNvData
->LocalIp
);
276 IScsiIpToStr (&SessionConfigData
->SubnetMask
, IfrNvData
->SubnetMask
);
277 IScsiIpToStr (&SessionConfigData
->Gateway
, IfrNvData
->Gateway
);
278 IScsiIpToStr (&SessionConfigData
->TargetIp
, IfrNvData
->TargetIp
);
280 IScsiAsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
282 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
285 // CHAP authentication parameters.
287 AuthConfigData
= &ConfigFormEntry
->AuthConfigData
;
289 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
291 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
292 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
293 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
294 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
298 This function allows a caller to extract the current configuration for one
299 or more named elements from the target driver.
301 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
303 @param Request[in] A null-terminated Unicode string in <ConfigRequest> format.
305 @param Progress[out] On return, points to a character in the Request string.
306 Points to the string's null terminator if request was successful.
307 Points to the most recent '&' before the first failing name/value
308 pair (or the beginning of the string if the failure is in the
309 first name/value pair) if the request was not successful.
311 @param Results[out] A null-terminated Unicode string in <ConfigAltResp> format which
312 has all values filled in for the names in the Request string.
313 String to be allocated by the called function.
315 @retval EFI_SUCCESS The Results is filled with the requested values.
317 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
319 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
321 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
326 IScsiFormExtractConfig (
327 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
328 IN CONST EFI_STRING Request
,
329 OUT EFI_STRING
*Progress
,
330 OUT EFI_STRING
*Results
334 CHAR8 InitiatorName
[ISCSI_NAME_IFR_MAX_SIZE
];
336 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
337 ISCSI_FORM_CALLBACK_INFO
*Private
;
338 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
340 if (!mIScsiDeviceListUpdated
) {
342 // Update the device list.
344 IScsiUpdateDeviceList ();
345 mIScsiDeviceListUpdated
= TRUE
;
348 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
349 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
350 ASSERT (IfrNvData
!= NULL
);
351 if (Private
->Current
!= NULL
) {
352 IScsiConvertDeviceConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
355 BufferSize
= ISCSI_NAME_IFR_MAX_SIZE
;
356 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
357 if (EFI_ERROR (Status
)) {
358 IfrNvData
->InitiatorName
[0] = L
'\0';
360 IScsiAsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
364 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
366 HiiConfigRouting
= Private
->ConfigRouting
;
367 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
368 Status
= HiiConfigRouting
->BlockToConfig (
376 gBS
->FreePool (IfrNvData
);
381 This function processes the results of changes in configuration.
383 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
385 @param Configuration[in] A null-terminated Unicode string in <ConfigResp> format.
387 @param Progress[out] A pointer to a string filled in with the offset of the most
388 recent '&' before the first failing name/value pair (or the
389 beginning of the string if the failure is in the first
390 name/value pair) or the terminating NULL if all was successful.
392 @retval EFI_SUCCESS The Results is processed successfully.
394 @retval EFI_INVALID_PARAMETER Configuration is NULL.
396 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
401 IScsiFormRouteConfig (
402 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
403 IN CONST EFI_STRING Configuration
,
404 OUT EFI_STRING
*Progress
411 This function processes the results of changes in configuration.
413 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
415 @param Action[in] Specifies the type of action taken by the browser.
417 @param QuestionId[in] A unique value which is sent to the original exporting driver
418 so that it can identify the type of data to expect.
420 @param Type[in] The type of value for the question.
422 @param Value[in] A pointer to the data being sent to the original exporting driver.
424 @param ActionRequest[out] On return, points to the action requested by the callback function.
426 @retval EFI_SUCCESS The callback successfully handled the action.
428 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
430 @retval EFI_DEVICE_ERROR The variable could not be saved.
432 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
438 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
439 IN EFI_BROWSER_ACTION Action
,
440 IN EFI_QUESTION_ID KeyValue
,
442 IN EFI_IFR_TYPE_VALUE
*Value
,
443 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
446 ISCSI_FORM_CALLBACK_INFO
*Private
;
448 CHAR8 IScsiName
[ISCSI_NAME_IFR_MAX_SIZE
];
449 CHAR16 PortString
[128];
450 CHAR8 Ip4String
[IP4_STR_MAX_SIZE
];
451 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
453 STRING_REF DeviceFormTitleToken
;
454 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
455 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
456 EFI_IP_ADDRESS HostIp
;
457 EFI_IP_ADDRESS SubnetMask
;
458 EFI_IP_ADDRESS Gateway
;
461 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
464 // Retrive uncommitted data from Browser
466 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
467 IfrNvData
= AllocateZeroPool (BufferSize
);
468 ASSERT (IfrNvData
!= NULL
);
469 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) IfrNvData
);
470 if (EFI_ERROR (Status
)) {
471 gBS
->FreePool (IfrNvData
);
476 case KEY_INITIATOR_NAME
:
477 IScsiUnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
478 BufferSize
= AsciiStrLen (IScsiName
) + 1;
480 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
481 if (EFI_ERROR (Status
)) {
482 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
488 IScsiUnicodeStrToAsciiStr (IfrNvData
->LocalIp
, Ip4String
);
489 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
490 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
491 PopUpInvalidNotify (L
"Invalid IP address!");
492 Status
= EFI_INVALID_PARAMETER
;
494 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
499 case KEY_SUBNET_MASK
:
500 IScsiUnicodeStrToAsciiStr (IfrNvData
->SubnetMask
, Ip4String
);
501 Status
= IScsiAsciiStrToIp (Ip4String
, &SubnetMask
.v4
);
502 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
503 PopUpInvalidNotify (L
"Invalid Subnet Mask!");
504 Status
= EFI_INVALID_PARAMETER
;
506 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
512 IScsiUnicodeStrToAsciiStr (IfrNvData
->Gateway
, Ip4String
);
513 Status
= IScsiAsciiStrToIp (Ip4String
, &Gateway
.v4
);
514 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
515 PopUpInvalidNotify (L
"Invalid Gateway!");
516 Status
= EFI_INVALID_PARAMETER
;
518 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
524 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetIp
, Ip4String
);
525 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
526 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
527 PopUpInvalidNotify (L
"Invalid IP address!");
528 Status
= EFI_INVALID_PARAMETER
;
530 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
535 case KEY_TARGET_NAME
:
536 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
537 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
538 if (EFI_ERROR (Status
)) {
539 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
541 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
546 case KEY_DHCP_ENABLE
:
547 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
548 IfrNvData
->TargetInfoFromDhcp
= 0;
554 IScsiUnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
555 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
556 if (EFI_ERROR (Status
)) {
557 PopUpInvalidNotify (L
"Invalid LUN string!");
559 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
565 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPName
, Private
->Current
->AuthConfigData
.CHAPName
);
568 case KEY_CHAP_SECRET
:
569 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPSecret
, Private
->Current
->AuthConfigData
.CHAPSecret
);
572 case KEY_REVERSE_CHAP_NAME
:
573 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPName
, Private
->Current
->AuthConfigData
.ReverseCHAPName
);
576 case KEY_REVERSE_CHAP_SECRET
:
577 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPSecret
, Private
->Current
->AuthConfigData
.ReverseCHAPSecret
);
580 case KEY_SAVE_CHANGES
:
582 // First, update those fields which don't have INTERACTIVE set.
584 Private
->Current
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
585 Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
586 Private
->Current
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
587 if (Private
->Current
->SessionConfigData
.TargetPort
== 0) {
588 Private
->Current
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
591 Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
592 Private
->Current
->AuthConfigData
.CHAPType
= IfrNvData
->CHAPType
;
595 // Only do full parameter validation if iSCSI is enabled on this device.
597 if (Private
->Current
->SessionConfigData
.Enabled
) {
599 // Validate the address configuration of the Initiator if DHCP isn't
602 if (!Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
) {
603 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
604 CopyMem (&SubnetMask
.v4
, &Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
605 CopyMem (&Gateway
.v4
, &Private
->Current
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
607 if ((Gateway
.Addr
[0] != 0)) {
608 if (SubnetMask
.Addr
[0] == 0) {
609 PopUpInvalidNotify (L
"Gateway address is set but subnet mask is zero.");
610 Status
= EFI_INVALID_PARAMETER
;
612 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
613 PopUpInvalidNotify (L
"Local IP and Gateway are not in the same subnet.");
614 Status
= EFI_INVALID_PARAMETER
;
620 // Validate target configuration if DHCP isn't deployed.
622 if (!Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
) {
623 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.TargetIp
, sizeof (HostIp
.v4
));
624 if (!Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
625 PopUpInvalidNotify (L
"Target IP is invalid!");
626 Status
= EFI_INVALID_PARAMETER
;
631 if (IfrNvData
->CHAPType
!= ISCSI_CHAP_NONE
) {
632 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
633 PopUpInvalidNotify (L
"CHAP Name or CHAP Secret is invalid!");
634 Status
= EFI_INVALID_PARAMETER
;
638 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
639 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
641 PopUpInvalidNotify (L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!");
642 Status
= EFI_INVALID_PARAMETER
;
648 BufferSize
= sizeof (Private
->Current
->SessionConfigData
);
650 Private
->Current
->MacString
,
651 &gEfiIScsiInitiatorNameProtocolGuid
,
652 ISCSI_CONFIG_VAR_ATTR
,
654 &Private
->Current
->SessionConfigData
657 BufferSize
= sizeof (Private
->Current
->AuthConfigData
);
659 Private
->Current
->MacString
,
660 &mIScsiCHAPAuthInfoGuid
,
661 ISCSI_CONFIG_VAR_ATTR
,
663 &Private
->Current
->AuthConfigData
665 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
669 if ((KeyValue
>= KEY_DEVICE_ENTRY_BASE
) && (KeyValue
< (mNumberOfIScsiDevices
+ KEY_DEVICE_ENTRY_BASE
))) {
671 // In case goto the device configuration form, update the device form title.
673 ConfigFormEntry
= IScsiGetConfigFormEntryByIndex ((UINT32
) (KeyValue
- KEY_DEVICE_ENTRY_BASE
));
674 ASSERT (ConfigFormEntry
!= NULL
);
676 UnicodeSPrint (PortString
, (UINTN
) 128, L
"Port %s", ConfigFormEntry
->MacString
);
677 DeviceFormTitleToken
= (STRING_REF
) STR_ISCSI_DEVICE_FORM_TITLE
;
678 HiiLibSetString (Private
->RegisteredHandle
, DeviceFormTitleToken
, PortString
);
680 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry
, IfrNvData
);
682 Private
->Current
= ConfigFormEntry
;
688 if (!EFI_ERROR (Status
)) {
690 // Pass changed uncommitted data back to Form Browser
692 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
693 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
696 gBS
->FreePool (IfrNvData
);
701 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
702 device specified by the Controller.
704 @param DriverBindingHandle[in] The driverbinding handle.
706 @param Controller[in] The controller handle of the iSCSI device.
708 @param AddForm[in] Whether to add or delete a form entry.
710 @retval EFI_SUCCESS The iSCSI configuration form is updated.
712 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
716 IScsiConfigUpdateForm (
717 IN EFI_HANDLE DriverBindingHandle
,
718 IN EFI_HANDLE Controller
,
723 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
724 BOOLEAN EntryExisted
;
726 EFI_HII_UPDATE_DATA UpdateData
;
727 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
728 CHAR16 PortString
[128];
733 ConfigFormEntry
= NULL
;
734 EntryExisted
= FALSE
;
736 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
737 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
739 if (ConfigFormEntry
->Controller
== Controller
) {
752 ConfigFormEntry
= (ISCSI_CONFIG_FORM_ENTRY
*) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY
));
753 if (ConfigFormEntry
== NULL
) {
754 return EFI_OUT_OF_RESOURCES
;
757 InitializeListHead (&ConfigFormEntry
->Link
);
758 ConfigFormEntry
->Controller
= Controller
;
761 // Get the simple network protocol and convert the MAC address into
762 // the formatted string.
764 Status
= gBS
->HandleProtocol (
766 &gEfiSimpleNetworkProtocolGuid
,
769 ASSERT (Status
== EFI_SUCCESS
);
771 IScsiMacAddrToStr (&Snp
->Mode
->PermanentAddress
, Snp
->Mode
->HwAddressSize
, ConfigFormEntry
->MacString
);
774 // Get the normal session configuration data.
776 BufferSize
= sizeof (ConfigFormEntry
->SessionConfigData
);
777 Status
= gRT
->GetVariable (
778 ConfigFormEntry
->MacString
,
779 &gEfiIScsiInitiatorNameProtocolGuid
,
782 &ConfigFormEntry
->SessionConfigData
784 if (EFI_ERROR (Status
)) {
785 ZeroMem (&ConfigFormEntry
->SessionConfigData
, sizeof (ConfigFormEntry
->SessionConfigData
));
788 // Get the CHAP authentication configuration data.
790 BufferSize
= sizeof (ConfigFormEntry
->AuthConfigData
);
791 Status
= gRT
->GetVariable (
792 ConfigFormEntry
->MacString
,
793 &mIScsiCHAPAuthInfoGuid
,
796 &ConfigFormEntry
->AuthConfigData
798 if (EFI_ERROR (Status
)) {
799 ZeroMem (&ConfigFormEntry
->AuthConfigData
, sizeof (ConfigFormEntry
->AuthConfigData
));
802 // Compose the Port string and create a new STRING_REF.
804 UnicodeSPrint (PortString
, 128, L
"Port %s", ConfigFormEntry
->MacString
);
805 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleToken
, PortString
);
808 // Compose the help string of this port and create a new STRING_REF.
810 UnicodeSPrint (PortString
, 128, L
"Set the iSCSI parameters on port %s", ConfigFormEntry
->MacString
);
811 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleHelpToken
, PortString
);
813 InsertTailList (&mIScsiConfigFormList
, &ConfigFormEntry
->Link
);
814 mNumberOfIScsiDevices
++;
817 ASSERT (EntryExisted
);
819 mNumberOfIScsiDevices
--;
820 RemoveEntryList (&ConfigFormEntry
->Link
);
821 gBS
->FreePool (ConfigFormEntry
);
824 // Allocate space for creation of Buffer
826 UpdateData
.BufferSize
= 0x1000;
827 UpdateData
.Data
= AllocateZeroPool (0x1000);
828 UpdateData
.Offset
= 0;
831 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
832 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
836 ConfigFormEntry
->PortTitleToken
,
837 ConfigFormEntry
->PortTitleHelpToken
,
838 EFI_IFR_FLAG_CALLBACK
,
839 (UINT16
)(KEY_DEVICE_ENTRY_BASE
+ FormIndex
),
847 mCallbackInfo
->RegisteredHandle
,
855 gBS
->FreePool (UpdateData
.Data
);
861 Initialize the iSCSI configuration form.
863 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
865 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
867 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
871 IScsiConfigFormInit (
872 IN EFI_HANDLE DriverBindingHandle
876 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
877 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
878 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
880 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**)&HiiDatabase
);
881 if (EFI_ERROR (Status
)) {
885 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
886 if (CallbackInfo
== NULL
) {
887 return EFI_OUT_OF_RESOURCES
;
890 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
891 CallbackInfo
->HiiDatabase
= HiiDatabase
;
892 CallbackInfo
->Current
= NULL
;
894 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
895 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
896 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
898 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**)&CallbackInfo
->ConfigRouting
);
899 if (EFI_ERROR (Status
)) {
900 FreePool(CallbackInfo
);
905 // Create driver handle used by HII database
907 Status
= HiiLibCreateHiiDriverHandle (&CallbackInfo
->DriverHandle
);
908 if (EFI_ERROR (Status
)) {
909 FreePool(CallbackInfo
);
914 // Install Config Access protocol to driver handle
916 Status
= gBS
->InstallProtocolInterface (
917 &CallbackInfo
->DriverHandle
,
918 &gEfiHiiConfigAccessProtocolGuid
,
919 EFI_NATIVE_INTERFACE
,
920 &CallbackInfo
->ConfigAccess
922 ASSERT_EFI_ERROR (Status
);
925 // Publish our HII data
927 PackageList
= HiiLibPreparePackageList (2, &mVendorGuid
, IScsiDxeStrings
, IScsiConfigDxeBin
);
928 ASSERT (PackageList
!= NULL
);
930 Status
= HiiDatabase
->NewPackageList (
933 CallbackInfo
->DriverHandle
,
934 &CallbackInfo
->RegisteredHandle
936 FreePool (PackageList
);
937 if (EFI_ERROR (Status
)) {
938 FreePool(CallbackInfo
);
942 mCallbackInfo
= CallbackInfo
;
948 Unload the iSCSI configuration form, this includes: delete all the iSCSI
949 device configuration entries, uninstall the form callback protocol and
950 free the resources used.
952 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
954 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
956 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
960 IScsiConfigFormUnload (
961 IN EFI_HANDLE DriverBindingHandle
964 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
966 while (!IsListEmpty (&mIScsiConfigFormList
)) {
968 // Uninstall the device forms as the iSCSI driver instance may fail to
969 // control the controller but still install the device configuration form.
970 // In such case, upon driver unloading, the driver instance's driverbinding.
971 // stop () won't be called, so we have to take this chance here to uninstall
974 ConfigFormEntry
= NET_LIST_USER_STRUCT (mIScsiConfigFormList
.ForwardLink
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
975 IScsiConfigUpdateForm (DriverBindingHandle
, ConfigFormEntry
->Controller
, FALSE
);
979 // Remove HII package list
981 mCallbackInfo
->HiiDatabase
->RemovePackageList (
982 mCallbackInfo
->HiiDatabase
,
983 mCallbackInfo
->RegisteredHandle
987 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
989 gBS
->UninstallProtocolInterface (
990 mCallbackInfo
->DriverHandle
,
991 &gEfiHiiConfigAccessProtocolGuid
,
992 &mCallbackInfo
->ConfigAccess
994 HiiLibDestroyHiiDriverHandle (mCallbackInfo
->DriverHandle
);
996 gBS
->FreePool (mCallbackInfo
);