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 (Request
== NULL
) {
339 return EFI_NOT_FOUND
;
342 if (!mIScsiDeviceListUpdated
) {
344 // Update the device list.
346 IScsiUpdateDeviceList ();
347 mIScsiDeviceListUpdated
= TRUE
;
350 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
351 IfrNvData
= AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA
));
352 ASSERT (IfrNvData
!= NULL
);
353 if (Private
->Current
!= NULL
) {
354 IScsiConvertDeviceConfigDataToIfrNvData (Private
->Current
, IfrNvData
);
357 BufferSize
= ISCSI_NAME_IFR_MAX_SIZE
;
358 Status
= gIScsiInitiatorName
.Get (&gIScsiInitiatorName
, &BufferSize
, InitiatorName
);
359 if (EFI_ERROR (Status
)) {
360 IfrNvData
->InitiatorName
[0] = L
'\0';
362 IScsiAsciiStrToUnicodeStr (InitiatorName
, IfrNvData
->InitiatorName
);
366 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
368 HiiConfigRouting
= Private
->ConfigRouting
;
369 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
370 Status
= HiiConfigRouting
->BlockToConfig (
378 gBS
->FreePool (IfrNvData
);
383 This function processes the results of changes in configuration.
385 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
387 @param Configuration[in] A null-terminated Unicode string in <ConfigResp> format.
389 @param Progress[out] A pointer to a string filled in with the offset of the most
390 recent '&' before the first failing name/value pair (or the
391 beginning of the string if the failure is in the first
392 name/value pair) or the terminating NULL if all was successful.
394 @retval EFI_SUCCESS The Results is processed successfully.
396 @retval EFI_INVALID_PARAMETER Configuration is NULL.
398 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
403 IScsiFormRouteConfig (
404 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
405 IN CONST EFI_STRING Configuration
,
406 OUT EFI_STRING
*Progress
413 This function processes the results of changes in configuration.
415 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
417 @param Action[in] Specifies the type of action taken by the browser.
419 @param QuestionId[in] A unique value which is sent to the original exporting driver
420 so that it can identify the type of data to expect.
422 @param Type[in] The type of value for the question.
424 @param Value[in] A pointer to the data being sent to the original exporting driver.
426 @param ActionRequest[out] On return, points to the action requested by the callback function.
428 @retval EFI_SUCCESS The callback successfully handled the action.
430 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.
432 @retval EFI_DEVICE_ERROR The variable could not be saved.
434 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.
440 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
441 IN EFI_BROWSER_ACTION Action
,
442 IN EFI_QUESTION_ID KeyValue
,
444 IN EFI_IFR_TYPE_VALUE
*Value
,
445 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
448 ISCSI_FORM_CALLBACK_INFO
*Private
;
450 CHAR8 IScsiName
[ISCSI_NAME_IFR_MAX_SIZE
];
451 CHAR16 PortString
[128];
452 CHAR8 Ip4String
[IP4_STR_MAX_SIZE
];
453 CHAR8 LunString
[ISCSI_LUN_STR_MAX_LEN
];
455 EFI_STRING_ID DeviceFormTitleToken
;
456 ISCSI_CONFIG_IFR_NVDATA
*IfrNvData
;
457 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
458 EFI_IP_ADDRESS HostIp
;
459 EFI_IP_ADDRESS SubnetMask
;
460 EFI_IP_ADDRESS Gateway
;
463 Private
= ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This
);
466 // Retrive uncommitted data from Browser
468 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
469 IfrNvData
= AllocateZeroPool (BufferSize
);
470 ASSERT (IfrNvData
!= NULL
);
471 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) IfrNvData
);
472 if (EFI_ERROR (Status
)) {
473 gBS
->FreePool (IfrNvData
);
478 case KEY_INITIATOR_NAME
:
479 IScsiUnicodeStrToAsciiStr (IfrNvData
->InitiatorName
, IScsiName
);
480 BufferSize
= AsciiStrLen (IScsiName
) + 1;
482 Status
= gIScsiInitiatorName
.Set (&gIScsiInitiatorName
, &BufferSize
, IScsiName
);
483 if (EFI_ERROR (Status
)) {
484 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
490 IScsiUnicodeStrToAsciiStr (IfrNvData
->LocalIp
, Ip4String
);
491 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
492 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
493 PopUpInvalidNotify (L
"Invalid IP address!");
494 Status
= EFI_INVALID_PARAMETER
;
496 CopyMem (&Private
->Current
->SessionConfigData
.LocalIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
501 case KEY_SUBNET_MASK
:
502 IScsiUnicodeStrToAsciiStr (IfrNvData
->SubnetMask
, Ip4String
);
503 Status
= IScsiAsciiStrToIp (Ip4String
, &SubnetMask
.v4
);
504 if (EFI_ERROR (Status
) || ((SubnetMask
.Addr
[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask
.v4
) == 0))) {
505 PopUpInvalidNotify (L
"Invalid Subnet Mask!");
506 Status
= EFI_INVALID_PARAMETER
;
508 CopyMem (&Private
->Current
->SessionConfigData
.SubnetMask
, &SubnetMask
.v4
, sizeof (SubnetMask
.v4
));
514 IScsiUnicodeStrToAsciiStr (IfrNvData
->Gateway
, Ip4String
);
515 Status
= IScsiAsciiStrToIp (Ip4String
, &Gateway
.v4
);
516 if (EFI_ERROR (Status
) || ((Gateway
.Addr
[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway
.Addr
[0]), 0))) {
517 PopUpInvalidNotify (L
"Invalid Gateway!");
518 Status
= EFI_INVALID_PARAMETER
;
520 CopyMem (&Private
->Current
->SessionConfigData
.Gateway
, &Gateway
.v4
, sizeof (Gateway
.v4
));
526 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetIp
, Ip4String
);
527 Status
= IScsiAsciiStrToIp (Ip4String
, &HostIp
.v4
);
528 if (EFI_ERROR (Status
) || !Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
529 PopUpInvalidNotify (L
"Invalid IP address!");
530 Status
= EFI_INVALID_PARAMETER
;
532 CopyMem (&Private
->Current
->SessionConfigData
.TargetIp
, &HostIp
.v4
, sizeof (HostIp
.v4
));
537 case KEY_TARGET_NAME
:
538 IScsiUnicodeStrToAsciiStr (IfrNvData
->TargetName
, IScsiName
);
539 Status
= IScsiNormalizeName (IScsiName
, AsciiStrLen (IScsiName
));
540 if (EFI_ERROR (Status
)) {
541 PopUpInvalidNotify (L
"Invalid iSCSI Name!");
543 AsciiStrCpy (Private
->Current
->SessionConfigData
.TargetName
, IScsiName
);
548 case KEY_DHCP_ENABLE
:
549 if (IfrNvData
->InitiatorInfoFromDhcp
== 0) {
550 IfrNvData
->TargetInfoFromDhcp
= 0;
556 IScsiUnicodeStrToAsciiStr (IfrNvData
->BootLun
, LunString
);
557 Status
= IScsiAsciiStrToLun (LunString
, (UINT8
*) &Lun
);
558 if (EFI_ERROR (Status
)) {
559 PopUpInvalidNotify (L
"Invalid LUN string!");
561 CopyMem (Private
->Current
->SessionConfigData
.BootLun
, &Lun
, sizeof (Lun
));
567 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPName
, Private
->Current
->AuthConfigData
.CHAPName
);
570 case KEY_CHAP_SECRET
:
571 IScsiUnicodeStrToAsciiStr (IfrNvData
->CHAPSecret
, Private
->Current
->AuthConfigData
.CHAPSecret
);
574 case KEY_REVERSE_CHAP_NAME
:
575 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPName
, Private
->Current
->AuthConfigData
.ReverseCHAPName
);
578 case KEY_REVERSE_CHAP_SECRET
:
579 IScsiUnicodeStrToAsciiStr (IfrNvData
->ReverseCHAPSecret
, Private
->Current
->AuthConfigData
.ReverseCHAPSecret
);
582 case KEY_SAVE_CHANGES
:
584 // First, update those fields which don't have INTERACTIVE set.
586 Private
->Current
->SessionConfigData
.Enabled
= IfrNvData
->Enabled
;
587 Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
= IfrNvData
->InitiatorInfoFromDhcp
;
588 Private
->Current
->SessionConfigData
.TargetPort
= IfrNvData
->TargetPort
;
589 if (Private
->Current
->SessionConfigData
.TargetPort
== 0) {
590 Private
->Current
->SessionConfigData
.TargetPort
= ISCSI_WELL_KNOWN_PORT
;
593 Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
= IfrNvData
->TargetInfoFromDhcp
;
594 Private
->Current
->AuthConfigData
.CHAPType
= IfrNvData
->CHAPType
;
597 // Only do full parameter validation if iSCSI is enabled on this device.
599 if (Private
->Current
->SessionConfigData
.Enabled
) {
601 // Validate the address configuration of the Initiator if DHCP isn't
604 if (!Private
->Current
->SessionConfigData
.InitiatorInfoFromDhcp
) {
605 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.LocalIp
, sizeof (HostIp
.v4
));
606 CopyMem (&SubnetMask
.v4
, &Private
->Current
->SessionConfigData
.SubnetMask
, sizeof (SubnetMask
.v4
));
607 CopyMem (&Gateway
.v4
, &Private
->Current
->SessionConfigData
.Gateway
, sizeof (Gateway
.v4
));
609 if ((Gateway
.Addr
[0] != 0)) {
610 if (SubnetMask
.Addr
[0] == 0) {
611 PopUpInvalidNotify (L
"Gateway address is set but subnet mask is zero.");
612 Status
= EFI_INVALID_PARAMETER
;
614 } else if (!IP4_NET_EQUAL (HostIp
.Addr
[0], Gateway
.Addr
[0], SubnetMask
.Addr
[0])) {
615 PopUpInvalidNotify (L
"Local IP and Gateway are not in the same subnet.");
616 Status
= EFI_INVALID_PARAMETER
;
622 // Validate target configuration if DHCP isn't deployed.
624 if (!Private
->Current
->SessionConfigData
.TargetInfoFromDhcp
) {
625 CopyMem (&HostIp
.v4
, &Private
->Current
->SessionConfigData
.TargetIp
, sizeof (HostIp
.v4
));
626 if (!Ip4IsUnicast (NTOHL (HostIp
.Addr
[0]), 0)) {
627 PopUpInvalidNotify (L
"Target IP is invalid!");
628 Status
= EFI_INVALID_PARAMETER
;
633 if (IfrNvData
->CHAPType
!= ISCSI_CHAP_NONE
) {
634 if ((IfrNvData
->CHAPName
[0] == '\0') || (IfrNvData
->CHAPSecret
[0] == '\0')) {
635 PopUpInvalidNotify (L
"CHAP Name or CHAP Secret is invalid!");
636 Status
= EFI_INVALID_PARAMETER
;
640 if ((IfrNvData
->CHAPType
== ISCSI_CHAP_MUTUAL
) &&
641 ((IfrNvData
->ReverseCHAPName
[0] == '\0') || (IfrNvData
->ReverseCHAPSecret
[0] == '\0'))
643 PopUpInvalidNotify (L
"Reverse CHAP Name or Reverse CHAP Secret is invalid!");
644 Status
= EFI_INVALID_PARAMETER
;
650 BufferSize
= sizeof (Private
->Current
->SessionConfigData
);
652 Private
->Current
->MacString
,
653 &gEfiIScsiInitiatorNameProtocolGuid
,
654 ISCSI_CONFIG_VAR_ATTR
,
656 &Private
->Current
->SessionConfigData
659 BufferSize
= sizeof (Private
->Current
->AuthConfigData
);
661 Private
->Current
->MacString
,
662 &mIScsiCHAPAuthInfoGuid
,
663 ISCSI_CONFIG_VAR_ATTR
,
665 &Private
->Current
->AuthConfigData
667 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
671 if ((KeyValue
>= KEY_DEVICE_ENTRY_BASE
) && (KeyValue
< (mNumberOfIScsiDevices
+ KEY_DEVICE_ENTRY_BASE
))) {
673 // In case goto the device configuration form, update the device form title.
675 ConfigFormEntry
= IScsiGetConfigFormEntryByIndex ((UINT32
) (KeyValue
- KEY_DEVICE_ENTRY_BASE
));
676 ASSERT (ConfigFormEntry
!= NULL
);
678 UnicodeSPrint (PortString
, (UINTN
) 128, L
"Port %s", ConfigFormEntry
->MacString
);
679 DeviceFormTitleToken
= (EFI_STRING_ID
) STR_ISCSI_DEVICE_FORM_TITLE
;
680 HiiLibSetString (Private
->RegisteredHandle
, DeviceFormTitleToken
, PortString
);
682 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry
, IfrNvData
);
684 Private
->Current
= ConfigFormEntry
;
690 if (!EFI_ERROR (Status
)) {
692 // Pass changed uncommitted data back to Form Browser
694 BufferSize
= sizeof (ISCSI_CONFIG_IFR_NVDATA
);
695 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
698 gBS
->FreePool (IfrNvData
);
703 Updates the iSCSI configuration form to add/delete an entry for the iSCSI
704 device specified by the Controller.
706 @param DriverBindingHandle[in] The driverbinding handle.
708 @param Controller[in] The controller handle of the iSCSI device.
710 @param AddForm[in] Whether to add or delete a form entry.
712 @retval EFI_SUCCESS The iSCSI configuration form is updated.
714 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
718 IScsiConfigUpdateForm (
719 IN EFI_HANDLE DriverBindingHandle
,
720 IN EFI_HANDLE Controller
,
725 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
726 BOOLEAN EntryExisted
;
728 EFI_HII_UPDATE_DATA UpdateData
;
729 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
730 CHAR16 PortString
[128];
735 ConfigFormEntry
= NULL
;
736 EntryExisted
= FALSE
;
738 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
739 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
741 if (ConfigFormEntry
->Controller
== Controller
) {
754 ConfigFormEntry
= (ISCSI_CONFIG_FORM_ENTRY
*) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY
));
755 if (ConfigFormEntry
== NULL
) {
756 return EFI_OUT_OF_RESOURCES
;
759 InitializeListHead (&ConfigFormEntry
->Link
);
760 ConfigFormEntry
->Controller
= Controller
;
763 // Get the simple network protocol and convert the MAC address into
764 // the formatted string.
766 Status
= gBS
->HandleProtocol (
768 &gEfiSimpleNetworkProtocolGuid
,
771 ASSERT (Status
== EFI_SUCCESS
);
773 IScsiMacAddrToStr (&Snp
->Mode
->PermanentAddress
, Snp
->Mode
->HwAddressSize
, ConfigFormEntry
->MacString
);
776 // Get the normal session configuration data.
778 BufferSize
= sizeof (ConfigFormEntry
->SessionConfigData
);
779 Status
= gRT
->GetVariable (
780 ConfigFormEntry
->MacString
,
781 &gEfiIScsiInitiatorNameProtocolGuid
,
784 &ConfigFormEntry
->SessionConfigData
786 if (EFI_ERROR (Status
)) {
787 ZeroMem (&ConfigFormEntry
->SessionConfigData
, sizeof (ConfigFormEntry
->SessionConfigData
));
790 // Get the CHAP authentication configuration data.
792 BufferSize
= sizeof (ConfigFormEntry
->AuthConfigData
);
793 Status
= gRT
->GetVariable (
794 ConfigFormEntry
->MacString
,
795 &mIScsiCHAPAuthInfoGuid
,
798 &ConfigFormEntry
->AuthConfigData
800 if (EFI_ERROR (Status
)) {
801 ZeroMem (&ConfigFormEntry
->AuthConfigData
, sizeof (ConfigFormEntry
->AuthConfigData
));
804 // Compose the Port string and create a new EFI_STRING_ID.
806 UnicodeSPrint (PortString
, 128, L
"Port %s", ConfigFormEntry
->MacString
);
807 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleToken
, PortString
);
810 // Compose the help string of this port and create a new EFI_STRING_ID.
812 UnicodeSPrint (PortString
, 128, L
"Set the iSCSI parameters on port %s", ConfigFormEntry
->MacString
);
813 HiiLibNewString (mCallbackInfo
->RegisteredHandle
, &ConfigFormEntry
->PortTitleHelpToken
, PortString
);
815 InsertTailList (&mIScsiConfigFormList
, &ConfigFormEntry
->Link
);
816 mNumberOfIScsiDevices
++;
819 ASSERT (EntryExisted
);
821 mNumberOfIScsiDevices
--;
822 RemoveEntryList (&ConfigFormEntry
->Link
);
823 gBS
->FreePool (ConfigFormEntry
);
826 // Allocate space for creation of Buffer
828 UpdateData
.BufferSize
= 0x1000;
829 UpdateData
.Data
= AllocateZeroPool (0x1000);
830 UpdateData
.Offset
= 0;
833 NET_LIST_FOR_EACH (Entry
, &mIScsiConfigFormList
) {
834 ConfigFormEntry
= NET_LIST_USER_STRUCT (Entry
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
838 ConfigFormEntry
->PortTitleToken
,
839 ConfigFormEntry
->PortTitleHelpToken
,
840 EFI_IFR_FLAG_CALLBACK
,
841 (UINT16
)(KEY_DEVICE_ENTRY_BASE
+ FormIndex
),
849 mCallbackInfo
->RegisteredHandle
,
857 gBS
->FreePool (UpdateData
.Data
);
863 Initialize the iSCSI configuration form.
865 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
867 @retval EFI_SUCCESS The iSCSI configuration form is initialized.
869 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
873 IScsiConfigFormInit (
874 IN EFI_HANDLE DriverBindingHandle
878 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
879 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
880 ISCSI_FORM_CALLBACK_INFO
*CallbackInfo
;
882 Status
= gBS
->LocateProtocol (&gEfiHiiDatabaseProtocolGuid
, NULL
, (VOID
**)&HiiDatabase
);
883 if (EFI_ERROR (Status
)) {
887 CallbackInfo
= (ISCSI_FORM_CALLBACK_INFO
*) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO
));
888 if (CallbackInfo
== NULL
) {
889 return EFI_OUT_OF_RESOURCES
;
892 CallbackInfo
->Signature
= ISCSI_FORM_CALLBACK_INFO_SIGNATURE
;
893 CallbackInfo
->HiiDatabase
= HiiDatabase
;
894 CallbackInfo
->Current
= NULL
;
896 CallbackInfo
->ConfigAccess
.ExtractConfig
= IScsiFormExtractConfig
;
897 CallbackInfo
->ConfigAccess
.RouteConfig
= IScsiFormRouteConfig
;
898 CallbackInfo
->ConfigAccess
.Callback
= IScsiFormCallback
;
900 Status
= gBS
->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid
, NULL
, (VOID
**)&CallbackInfo
->ConfigRouting
);
901 if (EFI_ERROR (Status
)) {
902 FreePool(CallbackInfo
);
907 // Create driver handle used by HII database
909 Status
= HiiLibCreateHiiDriverHandle (&CallbackInfo
->DriverHandle
);
910 if (EFI_ERROR (Status
)) {
911 FreePool(CallbackInfo
);
916 // Install Config Access protocol to driver handle
918 Status
= gBS
->InstallProtocolInterface (
919 &CallbackInfo
->DriverHandle
,
920 &gEfiHiiConfigAccessProtocolGuid
,
921 EFI_NATIVE_INTERFACE
,
922 &CallbackInfo
->ConfigAccess
924 ASSERT_EFI_ERROR (Status
);
927 // Publish our HII data
929 PackageList
= HiiLibPreparePackageList (2, &mVendorGuid
, IScsiDxeStrings
, IScsiConfigDxeBin
);
930 ASSERT (PackageList
!= NULL
);
932 Status
= HiiDatabase
->NewPackageList (
935 CallbackInfo
->DriverHandle
,
936 &CallbackInfo
->RegisteredHandle
938 FreePool (PackageList
);
939 if (EFI_ERROR (Status
)) {
940 FreePool(CallbackInfo
);
944 mCallbackInfo
= CallbackInfo
;
950 Unload the iSCSI configuration form, this includes: delete all the iSCSI
951 device configuration entries, uninstall the form callback protocol and
952 free the resources used.
954 @param DriverBindingHandle[in] The iSCSI driverbinding handle.
956 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.
958 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
962 IScsiConfigFormUnload (
963 IN EFI_HANDLE DriverBindingHandle
966 ISCSI_CONFIG_FORM_ENTRY
*ConfigFormEntry
;
968 while (!IsListEmpty (&mIScsiConfigFormList
)) {
970 // Uninstall the device forms as the iSCSI driver instance may fail to
971 // control the controller but still install the device configuration form.
972 // In such case, upon driver unloading, the driver instance's driverbinding.
973 // stop () won't be called, so we have to take this chance here to uninstall
976 ConfigFormEntry
= NET_LIST_USER_STRUCT (mIScsiConfigFormList
.ForwardLink
, ISCSI_CONFIG_FORM_ENTRY
, Link
);
977 IScsiConfigUpdateForm (DriverBindingHandle
, ConfigFormEntry
->Controller
, FALSE
);
981 // Remove HII package list
983 mCallbackInfo
->HiiDatabase
->RemovePackageList (
984 mCallbackInfo
->HiiDatabase
,
985 mCallbackInfo
->RegisteredHandle
989 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
991 gBS
->UninstallProtocolInterface (
992 mCallbackInfo
->DriverHandle
,
993 &gEfiHiiConfigAccessProtocolGuid
,
994 &mCallbackInfo
->ConfigAccess
996 HiiLibDestroyHiiDriverHandle (mCallbackInfo
->DriverHandle
);
998 gBS
->FreePool (mCallbackInfo
);