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.
47 IN EFI_IPv4_ADDRESS
*Ip
,
51 UnicodeSPrint ( Str
, 2 * IP4_STR_MAX_SIZE
, L
"%d.%d.%d.%d", Ip
->Addr
[0], Ip
->Addr
[1], Ip
->Addr
[2], Ip
->Addr
[3]);
55 Pop up an invalid notify which displays the message in Warning.
57 @param Warning[in] The warning message.
69 IfrLibCreatePopUp (1, &Key
, Warning
);
73 Update the list of iSCSI devices the iSCSI driver is controlling.
81 IScsiUpdateDeviceList (
86 ISCSI_DEVICE_LIST
*DeviceList
;
92 UINTN LastDeviceIndex
;
93 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
94 EFI_SIMPLE_NETWORK_MODE
*Mode
;
95 ISCSI_MAC_INFO
*CurMacInfo
;
96 ISCSI_MAC_INFO TempMacInfo
;
101 // Dump all the handles the Simple Network Protocol is installed on.
103 Status
= gBS
->LocateHandleBuffer (
105 &gEfiSimpleNetworkProtocolGuid
,
110 if (EFI_ERROR (Status
)) {
115 Status
= gRT
->GetVariable (
122 if (Status
== EFI_BUFFER_TOO_SMALL
) {
123 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DataSize
);
135 for (HandleIndex
= 0; HandleIndex
< NumHandles
; HandleIndex
++) {
136 gBS
->HandleProtocol (Handles
[HandleIndex
], &gEfiSimpleNetworkProtocolGuid
, (VOID
**)&Snp
);
140 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
141 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
142 if ((CurMacInfo
->Len
== Mode
->HwAddressSize
) &&
143 (NET_MAC_EQUAL (&CurMacInfo
->Mac
, &Mode
->PermanentAddress
, Mode
->HwAddressSize
))
146 // The previous configured NIC is still here.
148 if (Index
!= LastDeviceIndex
) {
150 // Swap the current MAC address entry with the one indexed by
153 CopyMem (&TempMacInfo
, CurMacInfo
, sizeof (ISCSI_MAC_INFO
));
154 CopyMem (CurMacInfo
, &DeviceList
->MacInfo
[LastDeviceIndex
], sizeof (ISCSI_MAC_INFO
));
155 CopyMem (&DeviceList
->MacInfo
[LastDeviceIndex
], &TempMacInfo
, sizeof (ISCSI_MAC_INFO
));
162 if (LastDeviceIndex
== DeviceList
->NumDevice
) {
167 for (Index
= LastDeviceIndex
; Index
< DeviceList
->NumDevice
; Index
++) {
169 // delete the variables
171 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
172 IScsiMacAddrToStr (&CurMacInfo
->Mac
, CurMacInfo
->Len
, MacString
);
173 gRT
->SetVariable (MacString
, &gEfiIScsiInitiatorNameProtocolGuid
, 0, 0, NULL
);
174 gRT
->SetVariable (MacString
, &mIScsiCHAPAuthInfoGuid
, 0, 0, NULL
);
177 gBS
->FreePool (DeviceList
);
178 } else if (Status
!= EFI_NOT_FOUND
) {
179 gBS
->FreePool (Handles
);
183 // Construct the new iSCSI device list.
185 DeviceListSize
= sizeof (ISCSI_DEVICE_LIST
) + (NumHandles
- 1) * sizeof (ISCSI_MAC_INFO
);
186 DeviceList
= (ISCSI_DEVICE_LIST
*) AllocatePool (DeviceListSize
);
187 DeviceList
->NumDevice
= (UINT8
) NumHandles
;
189 for (Index
= 0; Index
< NumHandles
; Index
++) {
190 gBS
->HandleProtocol (Handles
[Index
], &gEfiSimpleNetworkProtocolGuid
, (VOID
**)&Snp
);
193 CurMacInfo
= &DeviceList
->MacInfo
[Index
];
194 CopyMem (&CurMacInfo
->Mac
, &Mode
->PermanentAddress
, Mode
->HwAddressSize
);
195 CurMacInfo
->Len
= (UINT8
) Mode
->HwAddressSize
;
201 ISCSI_CONFIG_VAR_ATTR
,
206 gBS
->FreePool (DeviceList
);
207 gBS
->FreePool (Handles
);
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.
220 ISCSI_CONFIG_FORM_ENTRY
*
221 IScsiGetConfigFormEntryByIndex (
227 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
230 ConfigFormEntry
= NULL
;
232 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
233 if (CurrentIndex
== Index
) {
234 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
241 return ConfigFormEntry
;
245 Convert the iSCSI configuration data into the IFR data.
247 @param ConfigFormEntry[in] The iSCSI configuration form entry.
249 @param IfrNvData[in] The IFR nv data.
255 IScsiConvertDeviceConfigDataToIfrNvData (
256 IN ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
,
257 IN ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
260 ISCSI_SESSION_CONFIG_NVDATA
*SessionConfigData
;
261 ISCSI_CHAP_AUTH_CONFIG_NVDATA
*AuthConfigData
;
264 // Normal session configuration parameters.
266 SessionConfigData
= &ConfigFormEntry
->SessionConfigData
;
267 IfrNvData
->Enabled
= SessionConfigData
->Enabled
;
269 IfrNvData
->InitiatorInfoFromDhcp
= SessionConfigData
->InitiatorInfoFromDhcp
;
270 IfrNvData
->TargetInfoFromDhcp
= SessionConfigData
->TargetInfoFromDhcp
;
271 IfrNvData
->TargetPort
= SessionConfigData
->TargetPort
;
273 IScsiIpToStr (&SessionConfigData
->LocalIp
, IfrNvData
->LocalIp
);
274 IScsiIpToStr (&SessionConfigData
->SubnetMask
, IfrNvData
->SubnetMask
);
275 IScsiIpToStr (&SessionConfigData
->Gateway
, IfrNvData
->Gateway
);
276 IScsiIpToStr (&SessionConfigData
->TargetIp
, IfrNvData
->TargetIp
);
278 IScsiAsciiStrToUnicodeStr (SessionConfigData
->TargetName
, IfrNvData
->TargetName
);
280 IScsiLunToUnicodeStr (SessionConfigData
->BootLun
, IfrNvData
->BootLun
);
283 // CHAP authentication parameters.
285 AuthConfigData
= &ConfigFormEntry
->AuthConfigData
;
287 IfrNvData
->CHAPType
= AuthConfigData
->CHAPType
;
289 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPName
, IfrNvData
->CHAPName
);
290 IScsiAsciiStrToUnicodeStr (AuthConfigData
->CHAPSecret
, IfrNvData
->CHAPSecret
);
291 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPName
, IfrNvData
->ReverseCHAPName
);
292 IScsiAsciiStrToUnicodeStr (AuthConfigData
->ReverseCHAPSecret
, IfrNvData
->ReverseCHAPSecret
);
296 This function allows a caller to extract the current configuration for one
297 or more named elements from the target driver.
299 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
301 @param Request[in] A null-terminated Unicode string in <ConfigRequest> format.
303 @param Progress[out] On return, points to a character in the Request string.
304 Points to the string's null terminator if request was successful.
305 Points to the most recent '&' before the first failing name/value
306 pair (or the beginning of the string if the failure is in the
307 first name/value pair) if the request was not successful.
309 @param Results[out] A null-terminated Unicode string in <ConfigAltResp> format which
310 has all values filled in for the names in the Request string.
311 String to be allocated by the called function.
313 @retval EFI_SUCCESS The Results is filled with the requested values.
315 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
317 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
319 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
324 IScsiFormExtractConfig (
325 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
326 IN CONST EFI_STRING Request
,
327 OUT EFI_STRING
*Progress
,
328 OUT EFI_STRING
*Results
332 CHAR8 InitiatorName
[ISCSI_NAME_IFR_MAX_SIZE
];
334 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
335 ISCSI_FORM_CALLBACK_INFO
*Private
;
336 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
338 if (!mIScsiDeviceListUpdated
) {
340 // Update the device list.
342 IScsiUpdateDeviceList ();
343 mIScsiDeviceListUpdated
= TRUE
;
346 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
347 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
348 ASSERT (IfrNvData
!= NULL
);
349 if (Private
->Current
!= NULL
) {
350 IScsiConvertDeviceConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
353 BufferSize
= ISCSI_NAME_IFR_MAX_SIZE
;
354 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
355 if (EFI_ERROR (Status
)) {
356 IfrNvData
->InitiatorName
[0] = L
'\0';
358 IScsiAsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
362 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
364 HiiConfigRouting
= Private
->ConfigRouting
;
365 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
366 Status
= HiiConfigRouting
->BlockToConfig (
374 gBS
->FreePool (IfrNvData
);
379 This function processes the results of changes in configuration.
381 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
383 @param Configuration[in] A null-terminated Unicode string in <ConfigResp> format.
385 @param Progress[out] A pointer to a string filled in with the offset of the most
386 recent '&' before the first failing name/value pair (or the
387 beginning of the string if the failure is in the first
388 name/value pair) or the terminating NULL if all was successful.
390 @retval EFI_SUCCESS The Results is processed successfully.
392 @retval EFI_INVALID_PARAMETER Configuration is NULL.
394 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
399 IScsiFormRouteConfig (
400 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
401 IN CONST EFI_STRING Configuration
,
402 OUT EFI_STRING
*Progress
409 This function processes the results of changes in configuration.
411 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
413 @param Action[in] Specifies the type of action taken by the browser.
415 @param QuestionId[in] A unique value which is sent to the original exporting driver
416 so that it can identify the type of data to expect.
418 @param Type[in] The type of value for the question.
420 @param Value[in] A pointer to the data being sent to the original exporting driver.
422 @param ActionRequest[out] On return, points to the action requested by the callback function.
424 @retval EFI_SUCCESS The callback successfully handled the action.
426 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
428 @retval EFI_DEVICE_ERROR The variable could not be saved.
430 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
436 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
437 IN EFI_BROWSER_ACTION Action
,
438 IN EFI_QUESTION_ID KeyValue
,
440 IN EFI_IFR_TYPE_VALUE
*Value
,
441 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
444 ISCSI_FORM_CALLBACK_INFO
*Private
;
446 CHAR8 IScsiName
[ISCSI_NAME_IFR_MAX_SIZE
];
447 CHAR16 PortString
[128];
448 CHAR8 Ip4String
[IP4_STR_MAX_SIZE
];
449 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
451 EFI_STRING_ID DeviceFormTitleToken
;
452 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
453 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
454 EFI_IP_ADDRESS HostIp
;
455 EFI_IP_ADDRESS SubnetMask
;
456 EFI_IP_ADDRESS Gateway
;
459 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
462 // Retrive uncommitted data from Browser
464 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
465 IfrNvData
= AllocateZeroPool (BufferSize
);
466 ASSERT (IfrNvData
!= NULL
);
467 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) IfrNvData
);
468 if (EFI_ERROR (Status
)) {
469 gBS
->FreePool (IfrNvData
);
474 case KEY_INITIATOR_NAME
:
475 IScsiUnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
476 BufferSize
= AsciiStrLen (IScsiName
) + 1;
478 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
479 if (EFI_ERROR (Status
)) {
480 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
486 IScsiUnicodeStrToAsciiStr (IfrNvData
->LocalIp
, Ip4String
);
487 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
488 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
489 PopUpInvalidNotify (L
"Invalid IP address!");
490 Status
= EFI_INVALID_PARAMETER
;
492 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
497 case KEY_SUBNET_MASK
:
498 IScsiUnicodeStrToAsciiStr (IfrNvData
->SubnetMask
, Ip4String
);
499 Status
= IScsiAsciiStrToIp (Ip4String
, &SubnetMask
.v4
);
500 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
501 PopUpInvalidNotify (L
"Invalid Subnet Mask!");
502 Status
= EFI_INVALID_PARAMETER
;
504 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
510 IScsiUnicodeStrToAsciiStr (IfrNvData
->Gateway
, Ip4String
);
511 Status
= IScsiAsciiStrToIp (Ip4String
, &Gateway
.v4
);
512 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
513 PopUpInvalidNotify (L
"Invalid Gateway!");
514 Status
= EFI_INVALID_PARAMETER
;
516 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
522 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetIp
, Ip4String
);
523 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
524 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
525 PopUpInvalidNotify (L
"Invalid IP address!");
526 Status
= EFI_INVALID_PARAMETER
;
528 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
533 case KEY_TARGET_NAME
:
534 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
535 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
536 if (EFI_ERROR (Status
)) {
537 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
539 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
544 case KEY_DHCP_ENABLE
:
545 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
546 IfrNvData
->TargetInfoFromDhcp
= 0;
552 IScsiUnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
553 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
554 if (EFI_ERROR (Status
)) {
555 PopUpInvalidNotify (L
"Invalid LUN string!");
557 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
563 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPName
, Private
->Current
->AuthConfigData
.CHAPName
);
566 case KEY_CHAP_SECRET
:
567 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPSecret
, Private
->Current
->AuthConfigData
.CHAPSecret
);
570 case KEY_REVERSE_CHAP_NAME
:
571 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPName
, Private
->Current
->AuthConfigData
.ReverseCHAPName
);
574 case KEY_REVERSE_CHAP_SECRET
:
575 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPSecret
, Private
->Current
->AuthConfigData
.ReverseCHAPSecret
);
578 case KEY_SAVE_CHANGES
:
580 // First, update those fields which don't have INTERACTIVE set.
582 Private
->Current
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
583 Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
584 Private
->Current
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
585 if (Private
->Current
->SessionConfigData
.TargetPort
== 0) {
586 Private
->Current
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
589 Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
590 Private
->Current
->AuthConfigData
.CHAPType
= IfrNvData
->CHAPType
;
593 // Only do full parameter validation if iSCSI is enabled on this device.
595 if (Private
->Current
->SessionConfigData
.Enabled
) {
597 // Validate the address configuration of the Initiator if DHCP isn't
600 if (!Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
) {
601 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
602 CopyMem (&SubnetMask
.v4
, &Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
603 CopyMem (&Gateway
.v4
, &Private
->Current
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
605 if ((Gateway
.Addr
[0] != 0)) {
606 if (SubnetMask
.Addr
[0] == 0) {
607 PopUpInvalidNotify (L
"Gateway address is set but subnet mask is zero.");
608 Status
= EFI_INVALID_PARAMETER
;
610 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
611 PopUpInvalidNotify (L
"Local IP and Gateway are not in the same subnet.");
612 Status
= EFI_INVALID_PARAMETER
;
618 // Validate target configuration if DHCP isn't deployed.
620 if (!Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
) {
621 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.TargetIp
, sizeof (HostIp
.v4
));
622 if (!Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
623 PopUpInvalidNotify (L
"Target IP is invalid!");
624 Status
= EFI_INVALID_PARAMETER
;
629 if (IfrNvData
->CHAPType
!= ISCSI_CHAP_NONE
) {
630 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
631 PopUpInvalidNotify (L
"CHAP Name or CHAP Secret is invalid!");
632 Status
= EFI_INVALID_PARAMETER
;
636 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
637 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
639 PopUpInvalidNotify (L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!");
640 Status
= EFI_INVALID_PARAMETER
;
646 BufferSize
= sizeof (Private
->Current
->SessionConfigData
);
648 Private
->Current
->MacString
,
649 &gEfiIScsiInitiatorNameProtocolGuid
,
650 ISCSI_CONFIG_VAR_ATTR
,
652 &Private
->Current
->SessionConfigData
655 BufferSize
= sizeof (Private
->Current
->AuthConfigData
);
657 Private
->Current
->MacString
,
658 &mIScsiCHAPAuthInfoGuid
,
659 ISCSI_CONFIG_VAR_ATTR
,
661 &Private
->Current
->AuthConfigData
663 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
667 if ((KeyValue
>= KEY_DEVICE_ENTRY_BASE
) && (KeyValue
< (mNumberOfIScsiDevices
+ KEY_DEVICE_ENTRY_BASE
))) {
669 // In case goto the device configuration form, update the device form title.
671 ConfigFormEntry
= IScsiGetConfigFormEntryByIndex ((UINT32
) (KeyValue
- KEY_DEVICE_ENTRY_BASE
));
672 ASSERT (ConfigFormEntry
!= NULL
);
674 UnicodeSPrint (PortString
, (UINTN
) 128, L
"Port %s", ConfigFormEntry
->MacString
);
675 DeviceFormTitleToken
= (EFI_STRING_ID
) STR_ISCSI_DEVICE_FORM_TITLE
;
676 HiiLibSetString (Private
->RegisteredHandle
, DeviceFormTitleToken
, PortString
);
678 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry
, IfrNvData
);
680 Private
->Current
= ConfigFormEntry
;
686 if (!EFI_ERROR (Status
)) {
688 // Pass changed uncommitted data back to Form Browser
690 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
691 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
694 gBS
->FreePool (IfrNvData
);
699 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
700 device specified by the Controller.
702 @param DriverBindingHandle[in] The driverbinding handle.
704 @param Controller[in] The controller handle of the iSCSI device.
706 @param AddForm[in] Whether to add or delete a form entry.
708 @retval EFI_SUCCESS The iSCSI configuration form is updated.
710 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
714 IScsiConfigUpdateForm (
715 IN EFI_HANDLE DriverBindingHandle
,
716 IN EFI_HANDLE Controller
,
721 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
722 BOOLEAN EntryExisted
;
724 EFI_HII_UPDATE_DATA UpdateData
;
725 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
726 CHAR16 PortString
[128];
731 ConfigFormEntry
= NULL
;
732 EntryExisted
= FALSE
;
734 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
735 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
737 if (ConfigFormEntry
->Controller
== Controller
) {
750 ConfigFormEntry
= (ISCSI_CONFIG_FORM_ENTRY
*) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY
));
751 if (ConfigFormEntry
== NULL
) {
752 return EFI_OUT_OF_RESOURCES
;
755 InitializeListHead (&ConfigFormEntry
->Link
);
756 ConfigFormEntry
->Controller
= Controller
;
759 // Get the simple network protocol and convert the MAC address into
760 // the formatted string.
762 Status
= gBS
->HandleProtocol (
764 &gEfiSimpleNetworkProtocolGuid
,
767 ASSERT (Status
== EFI_SUCCESS
);
769 IScsiMacAddrToStr (&Snp
->Mode
->PermanentAddress
, Snp
->Mode
->HwAddressSize
, ConfigFormEntry
->MacString
);
772 // Get the normal session configuration data.
774 BufferSize
= sizeof (ConfigFormEntry
->SessionConfigData
);
775 Status
= gRT
->GetVariable (
776 ConfigFormEntry
->MacString
,
777 &gEfiIScsiInitiatorNameProtocolGuid
,
780 &ConfigFormEntry
->SessionConfigData
782 if (EFI_ERROR (Status
)) {
783 ZeroMem (&ConfigFormEntry
->SessionConfigData
, sizeof (ConfigFormEntry
->SessionConfigData
));
786 // Get the CHAP authentication configuration data.
788 BufferSize
= sizeof (ConfigFormEntry
->AuthConfigData
);
789 Status
= gRT
->GetVariable (
790 ConfigFormEntry
->MacString
,
791 &mIScsiCHAPAuthInfoGuid
,
794 &ConfigFormEntry
->AuthConfigData
796 if (EFI_ERROR (Status
)) {
797 ZeroMem (&ConfigFormEntry
->AuthConfigData
, sizeof (ConfigFormEntry
->AuthConfigData
));
800 // Compose the Port string and create a new EFI_STRING_ID.
802 UnicodeSPrint (PortString
, 128, L
"Port %s", ConfigFormEntry
->MacString
);
803 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleToken
, PortString
);
806 // Compose the help string of this port and create a new EFI_STRING_ID.
808 UnicodeSPrint (PortString
, 128, L
"Set the iSCSI parameters on port %s", ConfigFormEntry
->MacString
);
809 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleHelpToken
, PortString
);
811 InsertTailList (&mIScsiConfigFormList
, &ConfigFormEntry
->Link
);
812 mNumberOfIScsiDevices
++;
815 ASSERT (EntryExisted
);
817 mNumberOfIScsiDevices
--;
818 RemoveEntryList (&ConfigFormEntry
->Link
);
819 gBS
->FreePool (ConfigFormEntry
);
822 // Allocate space for creation of Buffer
824 UpdateData
.BufferSize
= 0x1000;
825 UpdateData
.Data
= AllocateZeroPool (0x1000);
826 UpdateData
.Offset
= 0;
829 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
830 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
834 ConfigFormEntry
->PortTitleToken
,
835 ConfigFormEntry
->PortTitleHelpToken
,
836 EFI_IFR_FLAG_CALLBACK
,
837 (UINT16
)(KEY_DEVICE_ENTRY_BASE
+ FormIndex
),
845 mCallbackInfo
->RegisteredHandle
,
853 gBS
->FreePool (UpdateData
.Data
);
859 Initialize the iSCSI configuration form.
861 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
863 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
865 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
869 IScsiConfigFormInit (
870 IN EFI_HANDLE DriverBindingHandle
874 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
875 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
876 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
878 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**)&HiiDatabase
);
879 if (EFI_ERROR (Status
)) {
883 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
884 if (CallbackInfo
== NULL
) {
885 return EFI_OUT_OF_RESOURCES
;
888 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
889 CallbackInfo
->HiiDatabase
= HiiDatabase
;
890 CallbackInfo
->Current
= NULL
;
892 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
893 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
894 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
896 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**)&CallbackInfo
->ConfigRouting
);
897 if (EFI_ERROR (Status
)) {
898 FreePool(CallbackInfo
);
903 // Create driver handle used by HII database
905 Status
= HiiLibCreateHiiDriverHandle (&CallbackInfo
->DriverHandle
);
906 if (EFI_ERROR (Status
)) {
907 FreePool(CallbackInfo
);
912 // Install Config Access protocol to driver handle
914 Status
= gBS
->InstallProtocolInterface (
915 &CallbackInfo
->DriverHandle
,
916 &gEfiHiiConfigAccessProtocolGuid
,
917 EFI_NATIVE_INTERFACE
,
918 &CallbackInfo
->ConfigAccess
920 ASSERT_EFI_ERROR (Status
);
923 // Publish our HII data
925 PackageList
= HiiLibPreparePackageList (2, &mVendorGuid
, IScsiDxeStrings
, IScsiConfigDxeBin
);
926 ASSERT (PackageList
!= NULL
);
928 Status
= HiiDatabase
->NewPackageList (
931 CallbackInfo
->DriverHandle
,
932 &CallbackInfo
->RegisteredHandle
934 FreePool (PackageList
);
935 if (EFI_ERROR (Status
)) {
936 FreePool(CallbackInfo
);
940 mCallbackInfo
= CallbackInfo
;
946 Unload the iSCSI configuration form, this includes: delete all the iSCSI
947 device configuration entries, uninstall the form callback protocol and
948 free the resources used.
950 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
952 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
954 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
958 IScsiConfigFormUnload (
959 IN EFI_HANDLE DriverBindingHandle
962 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
964 while (!IsListEmpty (&mIScsiConfigFormList
)) {
966 // Uninstall the device forms as the iSCSI driver instance may fail to
967 // control the controller but still install the device configuration form.
968 // In such case, upon driver unloading, the driver instance's driverbinding.
969 // stop () won't be called, so we have to take this chance here to uninstall
972 ConfigFormEntry
= NET_LIST_USER_STRUCT (mIScsiConfigFormList
.ForwardLink
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
973 IScsiConfigUpdateForm (DriverBindingHandle
, ConfigFormEntry
->Controller
, FALSE
);
977 // Remove HII package list
979 mCallbackInfo
->HiiDatabase
->RemovePackageList (
980 mCallbackInfo
->HiiDatabase
,
981 mCallbackInfo
->RegisteredHandle
985 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
987 gBS
->UninstallProtocolInterface (
988 mCallbackInfo
->DriverHandle
,
989 &gEfiHiiConfigAccessProtocolGuid
,
990 &mCallbackInfo
->ConfigAccess
992 HiiLibDestroyHiiDriverHandle (mCallbackInfo
->DriverHandle
);
994 gBS
->FreePool (mCallbackInfo
);