]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
Sync in bug fix from EDK I:
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiConfig.c
CommitLineData
12618416 1/** @file\r
2 Helper functions for configuring or getting the parameters relating to ISCSI\r
6a690e23 3\r
f2a94e25 4Copyright (c) 2004 - 2008, Intel Corporation\r
7a444476 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
6a690e23 12\r
13Module Name:\r
14\r
15 IScsiConfig.c\r
16\r
17Abstract:\r
18\r
12618416 19 Helper functions for configuring or getting the parameters relating to ISCSI\r
20\r
21**/\r
6a690e23 22\r
23#include "IScsiImpl.h"\r
24\r
f2a94e25 25EFI_GUID mVendorGuid = ISCSI_CONFIG_GUID;\r
26BOOLEAN mIScsiDeviceListUpdated = FALSE;\r
27UINTN mNumberOfIScsiDevices = 0;\r
28ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;\r
6a690e23 29\r
e48e37fc 30LIST_ENTRY mIScsiConfigFormList = {\r
6a690e23 31 &mIScsiConfigFormList,\r
32 &mIScsiConfigFormList\r
33};\r
34\r
12618416 35/**\r
36 Convert the IPv4 address into a dotted string.\r
37\r
38 @param Ip[in] The IPv4 address.\r
39\r
40 @param Str[out] The dotted IP string.\r
41\r
42 @retval None.\r
43\r
44**/\r
6a690e23 45VOID\r
46IScsiIpToStr (\r
47 IN EFI_IPv4_ADDRESS *Ip,\r
48 OUT CHAR16 *Str\r
49 )\r
6a690e23 50{\r
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]);\r
52}\r
53\r
12618416 54/**\r
6a690e23 55 Pop up an invalid notify which displays the message in Warning.\r
56\r
12618416 57 @param Warning[in] The warning message.\r
6a690e23 58\r
12618416 59 @retval None.\r
6a690e23 60\r
12618416 61**/\r
62VOID\r
63PopUpInvalidNotify (\r
64 IN CHAR16 *Warning\r
65 )\r
6a690e23 66{\r
6a690e23 67 EFI_INPUT_KEY Key;\r
6a690e23 68\r
93e3992d 69 IfrLibCreatePopUp (1, &Key, Warning);\r
6a690e23 70}\r
71\r
12618416 72/**\r
6a690e23 73 Update the list of iSCSI devices the iSCSI driver is controlling.\r
74\r
12618416 75 @param None.\r
6a690e23 76\r
12618416 77 @retval None.\r
6a690e23 78\r
12618416 79**/\r
80EFI_STATUS\r
81IScsiUpdateDeviceList (\r
82 VOID\r
83 )\r
6a690e23 84{\r
85 EFI_STATUS Status;\r
86 ISCSI_DEVICE_LIST *DeviceList;\r
87 UINTN DataSize;\r
88 UINTN NumHandles;\r
89 EFI_HANDLE *Handles;\r
90 UINTN HandleIndex;\r
91 UINTN Index;\r
92 UINTN LastDeviceIndex;\r
93 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
94 EFI_SIMPLE_NETWORK_MODE *Mode;\r
95 ISCSI_MAC_INFO *CurMacInfo;\r
96 ISCSI_MAC_INFO TempMacInfo;\r
97 CHAR16 MacString[65];\r
98 UINTN DeviceListSize;\r
99\r
100 //\r
101 // Dump all the handles the Simple Network Protocol is installed on.\r
102 //\r
103 Status = gBS->LocateHandleBuffer (\r
104 ByProtocol,\r
105 &gEfiSimpleNetworkProtocolGuid,\r
106 NULL,\r
107 &NumHandles,\r
108 &Handles\r
109 );\r
110 if (EFI_ERROR (Status)) {\r
111 return Status;\r
112 }\r
113\r
114 DataSize = 0;\r
115 Status = gRT->GetVariable (\r
116 L"iSCSIDeviceList",\r
117 &mVendorGuid,\r
118 NULL,\r
119 &DataSize,\r
120 NULL\r
121 );\r
122 if (Status == EFI_BUFFER_TOO_SMALL) {\r
e48e37fc 123 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DataSize);\r
6a690e23 124\r
125 gRT->GetVariable (\r
126 L"iSCSIDeviceList",\r
127 &mVendorGuid,\r
128 NULL,\r
129 &DataSize,\r
130 DeviceList\r
131 );\r
132\r
133 LastDeviceIndex = 0;\r
134\r
135 for (HandleIndex = 0; HandleIndex < NumHandles; HandleIndex++) {\r
136 gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
137\r
138 Mode = Snp->Mode;\r
139\r
140 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
141 CurMacInfo = &DeviceList->MacInfo[Index];\r
142 if ((CurMacInfo->Len == Mode->HwAddressSize) &&\r
143 (NET_MAC_EQUAL (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize))\r
144 ) {\r
145 //\r
146 // The previous configured NIC is still here.\r
147 //\r
148 if (Index != LastDeviceIndex) {\r
149 //\r
150 // Swap the current MAC address entry with the one indexed by\r
151 // LastDeviceIndex.\r
152 //\r
e48e37fc 153 CopyMem (&TempMacInfo, CurMacInfo, sizeof (ISCSI_MAC_INFO));\r
154 CopyMem (CurMacInfo, &DeviceList->MacInfo[LastDeviceIndex], sizeof (ISCSI_MAC_INFO));\r
155 CopyMem (&DeviceList->MacInfo[LastDeviceIndex], &TempMacInfo, sizeof (ISCSI_MAC_INFO));\r
6a690e23 156 }\r
157\r
158 LastDeviceIndex++;\r
159 }\r
160 }\r
161\r
162 if (LastDeviceIndex == DeviceList->NumDevice) {\r
163 break;\r
164 }\r
165 }\r
166\r
167 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
168 //\r
169 // delete the variables\r
170 //\r
171 CurMacInfo = &DeviceList->MacInfo[Index];\r
172 IScsiMacAddrToStr (&CurMacInfo->Mac, CurMacInfo->Len, MacString);\r
173 gRT->SetVariable (MacString, &gEfiIScsiInitiatorNameProtocolGuid, 0, 0, NULL);\r
174 gRT->SetVariable (MacString, &mIScsiCHAPAuthInfoGuid, 0, 0, NULL);\r
175 }\r
176\r
e48e37fc 177 gBS->FreePool (DeviceList);\r
6a690e23 178 } else if (Status != EFI_NOT_FOUND) {\r
e48e37fc 179 gBS->FreePool (Handles);\r
6a690e23 180 return Status;\r
181 }\r
182 //\r
183 // Construct the new iSCSI device list.\r
184 //\r
185 DeviceListSize = sizeof (ISCSI_DEVICE_LIST) + (NumHandles - 1) * sizeof (ISCSI_MAC_INFO);\r
e48e37fc 186 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DeviceListSize);\r
6a690e23 187 DeviceList->NumDevice = (UINT8) NumHandles;\r
188\r
189 for (Index = 0; Index < NumHandles; Index++) {\r
190 gBS->HandleProtocol (Handles[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&Snp);\r
191 Mode = Snp->Mode;\r
192\r
193 CurMacInfo = &DeviceList->MacInfo[Index];\r
e48e37fc 194 CopyMem (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize);\r
6a690e23 195 CurMacInfo->Len = (UINT8) Mode->HwAddressSize;\r
196 }\r
197\r
198 gRT->SetVariable (\r
199 L"iSCSIDeviceList",\r
200 &mVendorGuid,\r
201 ISCSI_CONFIG_VAR_ATTR,\r
202 DeviceListSize,\r
203 DeviceList\r
204 );\r
205\r
e48e37fc 206 gBS->FreePool (DeviceList);\r
356e635c 207 gBS->FreePool (Handles);\r
6a690e23 208\r
209 return Status;\r
210}\r
211\r
12618416 212/**\r
213 Get the iSCSI configuration form entry by the index of the goto opcode actived.\r
214\r
215 @param Index[in] The 0-based index of the goto opcode actived.\r
216\r
217 @retval The iSCSI configuration form entry found.\r
218\r
219**/\r
6a690e23 220ISCSI_CONFIG_FORM_ENTRY *\r
221IScsiGetConfigFormEntryByIndex (\r
222 IN UINT32 Index\r
223 )\r
6a690e23 224{\r
225 UINT32 CurrentIndex;\r
e48e37fc 226 LIST_ENTRY *Entry;\r
6a690e23 227 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
228\r
229 CurrentIndex = 0;\r
230 ConfigFormEntry = NULL;\r
231\r
232 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
233 if (CurrentIndex == Index) {\r
234 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
235 break;\r
236 }\r
237\r
238 CurrentIndex++;\r
239 }\r
240\r
241 return ConfigFormEntry;\r
242}\r
243\r
12618416 244/**\r
245 Convert the iSCSI configuration data into the IFR data.\r
246\r
247 @param ConfigFormEntry[in] The iSCSI configuration form entry.\r
248\r
249 @param IfrNvData[in] The IFR nv data.\r
250\r
251 @retval None.\r
252\r
253**/\r
6a690e23 254VOID\r
255IScsiConvertDeviceConfigDataToIfrNvData (\r
256 IN ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
257 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
258 )\r
6a690e23 259{\r
260 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;\r
261 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
262\r
263 //\r
264 // Normal session configuration parameters.\r
265 //\r
266 SessionConfigData = &ConfigFormEntry->SessionConfigData;\r
267 IfrNvData->Enabled = SessionConfigData->Enabled;\r
268\r
269 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;\r
270 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;\r
271 IfrNvData->TargetPort = SessionConfigData->TargetPort;\r
272\r
273 IScsiIpToStr (&SessionConfigData->LocalIp, IfrNvData->LocalIp);\r
274 IScsiIpToStr (&SessionConfigData->SubnetMask, IfrNvData->SubnetMask);\r
275 IScsiIpToStr (&SessionConfigData->Gateway, IfrNvData->Gateway);\r
276 IScsiIpToStr (&SessionConfigData->TargetIp, IfrNvData->TargetIp);\r
277\r
278 IScsiAsciiStrToUnicodeStr (SessionConfigData->TargetName, IfrNvData->TargetName);\r
279\r
280 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);\r
281\r
282 //\r
283 // CHAP authentication parameters.\r
284 //\r
285 AuthConfigData = &ConfigFormEntry->AuthConfigData;\r
286\r
287 IfrNvData->CHAPType = AuthConfigData->CHAPType;\r
288\r
289 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPName, IfrNvData->CHAPName);\r
290 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPSecret, IfrNvData->CHAPSecret);\r
291 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPName, IfrNvData->ReverseCHAPName);\r
292 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);\r
293}\r
294\r
12618416 295/**\r
296 This function allows a caller to extract the current configuration for one\r
297 or more named elements from the target driver.\r
298\r
299 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
300\r
301 @param Request[in] A null-terminated Unicode string in <ConfigRequest> format.\r
93e3992d 302\r
12618416 303 @param Progress[out] On return, points to a character in the Request string.\r
304 Points to the string's null terminator if request was successful.\r
305 Points to the most recent '&' before the first failing name/value\r
306 pair (or the beginning of the string if the failure is in the\r
307 first name/value pair) if the request was not successful.\r
308\r
309 @param Results[out] A null-terminated Unicode string in <ConfigAltResp> format which\r
310 has all values filled in for the names in the Request string.\r
311 String to be allocated by the called function.\r
312\r
313 @retval EFI_SUCCESS The Results is filled with the requested values.\r
314\r
315 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
316\r
317 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
318\r
319 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
320\r
321**/\r
6a690e23 322EFI_STATUS\r
323EFIAPI\r
93e3992d 324IScsiFormExtractConfig (\r
325 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
326 IN CONST EFI_STRING Request,\r
327 OUT EFI_STRING *Progress,\r
328 OUT EFI_STRING *Results\r
6a690e23 329 )\r
6a690e23 330{\r
93e3992d 331 EFI_STATUS Status;\r
332 CHAR8 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];\r
333 UINTN BufferSize;\r
334 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
335 ISCSI_FORM_CALLBACK_INFO *Private;\r
336 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
6a690e23 337\r
338 if (!mIScsiDeviceListUpdated) {\r
339 //\r
340 // Update the device list.\r
341 //\r
342 IScsiUpdateDeviceList ();\r
343 mIScsiDeviceListUpdated = TRUE;\r
344 }\r
345\r
93e3992d 346 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
347 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
348 ASSERT (IfrNvData != NULL);\r
349 if (Private->Current != NULL) {\r
350 IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
351 }\r
6a690e23 352\r
93e3992d 353 BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
6a690e23 354 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
355 if (EFI_ERROR (Status)) {\r
356 IfrNvData->InitiatorName[0] = L'\0';\r
357 } else {\r
358 IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
359 }\r
360\r
93e3992d 361 //\r
362 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
363 //\r
364 HiiConfigRouting = Private->ConfigRouting;\r
365 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
366 Status = HiiConfigRouting->BlockToConfig (\r
367 HiiConfigRouting,\r
368 Request,\r
369 (UINT8 *) IfrNvData,\r
370 BufferSize,\r
371 Results,\r
372 Progress\r
373 );\r
e48e37fc 374 gBS->FreePool (IfrNvData);\r
93e3992d 375 return Status;\r
6a690e23 376}\r
377\r
12618416 378/**\r
379 This function processes the results of changes in configuration.\r
380\r
381 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
382\r
383 @param Configuration[in] A null-terminated Unicode string in <ConfigResp> format.\r
384\r
385 @param Progress[out] A pointer to a string filled in with the offset of the most\r
386 recent '&' before the first failing name/value pair (or the\r
387 beginning of the string if the failure is in the first\r
388 name/value pair) or the terminating NULL if all was successful.\r
389\r
390 @retval EFI_SUCCESS The Results is processed successfully.\r
391\r
392 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
393\r
394 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
395\r
396**/\r
6a690e23 397EFI_STATUS\r
398EFIAPI\r
93e3992d 399IScsiFormRouteConfig (\r
400 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
401 IN CONST EFI_STRING Configuration,\r
402 OUT EFI_STRING *Progress\r
6a690e23 403 )\r
12618416 404{\r
405 return EFI_SUCCESS;\r
406}\r
6a690e23 407\r
12618416 408/**\r
409 This function processes the results of changes in configuration.\r
6a690e23 410\r
12618416 411 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
6a690e23 412\r
12618416 413 @param Action[in] Specifies the type of action taken by the browser.\r
6a690e23 414\r
12618416 415 @param QuestionId[in] A unique value which is sent to the original exporting driver\r
416 so that it can identify the type of data to expect.\r
417\r
418 @param Type[in] The type of value for the question.\r
419\r
420 @param Value[in] A pointer to the data being sent to the original exporting driver.\r
421\r
422 @param ActionRequest[out] On return, points to the action requested by the callback function.\r
423\r
424 @retval EFI_SUCCESS The callback successfully handled the action.\r
425\r
426 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
6a690e23 427\r
12618416 428 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
429\r
430 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
431\r
432**/\r
93e3992d 433EFI_STATUS\r
434EFIAPI\r
435IScsiFormCallback (\r
436 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
437 IN EFI_BROWSER_ACTION Action,\r
438 IN EFI_QUESTION_ID KeyValue,\r
439 IN UINT8 Type,\r
440 IN EFI_IFR_TYPE_VALUE *Value,\r
441 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
442 )\r
6a690e23 443{\r
444 ISCSI_FORM_CALLBACK_INFO *Private;\r
445 UINTN BufferSize;\r
446 CHAR8 IScsiName[ISCSI_NAME_IFR_MAX_SIZE];\r
447 CHAR16 PortString[128];\r
448 CHAR8 Ip4String[IP4_STR_MAX_SIZE];\r
449 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
450 UINT64 Lun;\r
6c7a807a 451 EFI_STRING_ID DeviceFormTitleToken;\r
6a690e23 452 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
453 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
454 EFI_IP_ADDRESS HostIp;\r
455 EFI_IP_ADDRESS SubnetMask;\r
456 EFI_IP_ADDRESS Gateway;\r
457 EFI_STATUS Status;\r
458\r
459 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
93e3992d 460\r
461 //\r
462 // Retrive uncommitted data from Browser\r
463 //\r
464 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
465 IfrNvData = AllocateZeroPool (BufferSize);\r
466 ASSERT (IfrNvData != NULL);\r
467 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) IfrNvData);\r
468 if (EFI_ERROR (Status)) {\r
469 gBS->FreePool (IfrNvData);\r
470 return Status;\r
471 }\r
6a690e23 472\r
473 switch (KeyValue) {\r
474 case KEY_INITIATOR_NAME:\r
475 IScsiUnicodeStrToAsciiStr (IfrNvData->InitiatorName, IScsiName);\r
476 BufferSize = AsciiStrLen (IScsiName) + 1;\r
477\r
478 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
479 if (EFI_ERROR (Status)) {\r
480 PopUpInvalidNotify (L"Invalid iSCSI Name!");\r
481 }\r
482\r
483 break;\r
484\r
485 case KEY_LOCAL_IP:\r
486 IScsiUnicodeStrToAsciiStr (IfrNvData->LocalIp, Ip4String);\r
487 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
488 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
489 PopUpInvalidNotify (L"Invalid IP address!");\r
490 Status = EFI_INVALID_PARAMETER;\r
491 } else {\r
e48e37fc 492 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 493 }\r
494\r
495 break;\r
496\r
497 case KEY_SUBNET_MASK:\r
498 IScsiUnicodeStrToAsciiStr (IfrNvData->SubnetMask, Ip4String);\r
499 Status = IScsiAsciiStrToIp (Ip4String, &SubnetMask.v4);\r
500 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
501 PopUpInvalidNotify (L"Invalid Subnet Mask!");\r
502 Status = EFI_INVALID_PARAMETER;\r
503 } else {\r
e48e37fc 504 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
6a690e23 505 }\r
506\r
507 break;\r
508\r
509 case KEY_GATE_WAY:\r
510 IScsiUnicodeStrToAsciiStr (IfrNvData->Gateway, Ip4String);\r
511 Status = IScsiAsciiStrToIp (Ip4String, &Gateway.v4);\r
512 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
513 PopUpInvalidNotify (L"Invalid Gateway!");\r
514 Status = EFI_INVALID_PARAMETER;\r
515 } else {\r
e48e37fc 516 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
6a690e23 517 }\r
518\r
519 break;\r
520\r
521 case KEY_TARGET_IP:\r
522 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetIp, Ip4String);\r
523 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
524 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
525 PopUpInvalidNotify (L"Invalid IP address!");\r
526 Status = EFI_INVALID_PARAMETER;\r
527 } else {\r
e48e37fc 528 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 529 }\r
530\r
531 break;\r
532\r
533 case KEY_TARGET_NAME:\r
534 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetName, IScsiName);\r
535 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
536 if (EFI_ERROR (Status)) {\r
537 PopUpInvalidNotify (L"Invalid iSCSI Name!");\r
538 } else {\r
539 AsciiStrCpy (Private->Current->SessionConfigData.TargetName, IScsiName);\r
540 }\r
541\r
542 break;\r
543\r
544 case KEY_DHCP_ENABLE:\r
545 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
546 IfrNvData->TargetInfoFromDhcp = 0;\r
547 }\r
548\r
549 break;\r
550\r
551 case KEY_BOOT_LUN:\r
552 IScsiUnicodeStrToAsciiStr (IfrNvData->BootLun, LunString);\r
553 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
554 if (EFI_ERROR (Status)) {\r
555 PopUpInvalidNotify (L"Invalid LUN string!");\r
556 } else {\r
e48e37fc 557 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
6a690e23 558 }\r
559\r
560 break;\r
561\r
562 case KEY_CHAP_NAME:\r
563 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPName, Private->Current->AuthConfigData.CHAPName);\r
564 break;\r
565\r
566 case KEY_CHAP_SECRET:\r
567 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPSecret, Private->Current->AuthConfigData.CHAPSecret);\r
568 break;\r
569\r
570 case KEY_REVERSE_CHAP_NAME:\r
571 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPName, Private->Current->AuthConfigData.ReverseCHAPName);\r
572 break;\r
573\r
574 case KEY_REVERSE_CHAP_SECRET:\r
575 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPSecret, Private->Current->AuthConfigData.ReverseCHAPSecret);\r
576 break;\r
577\r
578 case KEY_SAVE_CHANGES:\r
579 //\r
580 // First, update those fields which don't have INTERACTIVE set.\r
581 //\r
582 Private->Current->SessionConfigData.Enabled = IfrNvData->Enabled;\r
583 Private->Current->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
584 Private->Current->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
585 if (Private->Current->SessionConfigData.TargetPort == 0) {\r
586 Private->Current->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
587 }\r
588\r
589 Private->Current->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
590 Private->Current->AuthConfigData.CHAPType = IfrNvData->CHAPType;\r
591\r
592 //\r
593 // Only do full parameter validation if iSCSI is enabled on this device.\r
594 //\r
595 if (Private->Current->SessionConfigData.Enabled) {\r
596 //\r
597 // Validate the address configuration of the Initiator if DHCP isn't\r
598 // deployed.\r
599 //\r
600 if (!Private->Current->SessionConfigData.InitiatorInfoFromDhcp) {\r
e48e37fc 601 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
602 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
603 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
6a690e23 604\r
605 if ((Gateway.Addr[0] != 0)) {\r
606 if (SubnetMask.Addr[0] == 0) {\r
607 PopUpInvalidNotify (L"Gateway address is set but subnet mask is zero.");\r
608 Status = EFI_INVALID_PARAMETER;\r
609 break;\r
610 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
611 PopUpInvalidNotify (L"Local IP and Gateway are not in the same subnet.");\r
612 Status = EFI_INVALID_PARAMETER;\r
613 break;\r
614 }\r
615 }\r
616 }\r
617 //\r
618 // Validate target configuration if DHCP isn't deployed.\r
619 //\r
620 if (!Private->Current->SessionConfigData.TargetInfoFromDhcp) {\r
e48e37fc 621 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
6a690e23 622 if (!Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
623 PopUpInvalidNotify (L"Target IP is invalid!");\r
624 Status = EFI_INVALID_PARAMETER;\r
625 break;\r
626 }\r
627 }\r
628\r
629 if (IfrNvData->CHAPType != ISCSI_CHAP_NONE) {\r
630 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
631 PopUpInvalidNotify (L"CHAP Name or CHAP Secret is invalid!");\r
632 Status = EFI_INVALID_PARAMETER;\r
633 break;\r
634 }\r
635\r
636 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
637 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
638 ) {\r
639 PopUpInvalidNotify (L"Reverse CHAP Name or Reverse CHAP Secret is invalid!");\r
640 Status = EFI_INVALID_PARAMETER;\r
641 break;\r
642 }\r
643 }\r
644 }\r
645\r
646 BufferSize = sizeof (Private->Current->SessionConfigData);\r
647 gRT->SetVariable (\r
648 Private->Current->MacString,\r
649 &gEfiIScsiInitiatorNameProtocolGuid,\r
650 ISCSI_CONFIG_VAR_ATTR,\r
651 BufferSize,\r
652 &Private->Current->SessionConfigData\r
653 );\r
654\r
655 BufferSize = sizeof (Private->Current->AuthConfigData);\r
656 gRT->SetVariable (\r
657 Private->Current->MacString,\r
658 &mIScsiCHAPAuthInfoGuid,\r
659 ISCSI_CONFIG_VAR_ATTR,\r
660 BufferSize,\r
661 &Private->Current->AuthConfigData\r
662 );\r
93e3992d 663 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
6a690e23 664 break;\r
665\r
666 default:\r
667 if ((KeyValue >= KEY_DEVICE_ENTRY_BASE) && (KeyValue < (mNumberOfIScsiDevices + KEY_DEVICE_ENTRY_BASE))) {\r
668 //\r
669 // In case goto the device configuration form, update the device form title.\r
670 //\r
671 ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (KeyValue - KEY_DEVICE_ENTRY_BASE));\r
672 ASSERT (ConfigFormEntry != NULL);\r
673\r
93e3992d 674 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
6c7a807a 675 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;\r
9226efe5 676 HiiLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);\r
6a690e23 677\r
678 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
679\r
680 Private->Current = ConfigFormEntry;\r
681 }\r
682\r
683 break;\r
684 }\r
685\r
93e3992d 686 if (!EFI_ERROR (Status)) {\r
687 //\r
688 // Pass changed uncommitted data back to Form Browser\r
689 //\r
690 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
691 Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
692 }\r
693\r
e48e37fc 694 gBS->FreePool (IfrNvData);\r
6a690e23 695 return Status;\r
696}\r
697\r
12618416 698/**\r
6a690e23 699 Updates the iSCSI configuration form to add/delete an entry for the iSCSI\r
700 device specified by the Controller.\r
701\r
12618416 702 @param DriverBindingHandle[in] The driverbinding handle.\r
703\r
704 @param Controller[in] The controller handle of the iSCSI device.\r
6a690e23 705\r
12618416 706 @param AddForm[in] Whether to add or delete a form entry.\r
6a690e23 707\r
12618416 708 @retval EFI_SUCCESS The iSCSI configuration form is updated.\r
6a690e23 709\r
12618416 710 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
6a690e23 711\r
12618416 712**/\r
713EFI_STATUS\r
714IScsiConfigUpdateForm (\r
715 IN EFI_HANDLE DriverBindingHandle,\r
716 IN EFI_HANDLE Controller,\r
717 IN BOOLEAN AddForm\r
718 )\r
6a690e23 719{\r
e48e37fc 720 LIST_ENTRY *Entry;\r
6a690e23 721 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
722 BOOLEAN EntryExisted;\r
6a690e23 723 EFI_STATUS Status;\r
93e3992d 724 EFI_HII_UPDATE_DATA UpdateData;\r
6a690e23 725 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
726 CHAR16 PortString[128];\r
727 UINT16 FormIndex;\r
728 UINTN BufferSize;\r
729\r
6a690e23 730\r
731 ConfigFormEntry = NULL;\r
732 EntryExisted = FALSE;\r
733\r
734 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
735 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
736\r
737 if (ConfigFormEntry->Controller == Controller) {\r
738 EntryExisted = TRUE;\r
739 break;\r
740 }\r
741 }\r
742\r
743 if (AddForm) {\r
744 if (EntryExisted) {\r
745 return EFI_SUCCESS;\r
746 } else {\r
747 //\r
748 // Add a new form.\r
749 //\r
e48e37fc 750 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
6a690e23 751 if (ConfigFormEntry == NULL) {\r
752 return EFI_OUT_OF_RESOURCES;\r
753 }\r
754\r
e48e37fc 755 InitializeListHead (&ConfigFormEntry->Link);\r
6a690e23 756 ConfigFormEntry->Controller = Controller;\r
757\r
758 //\r
759 // Get the simple network protocol and convert the MAC address into\r
760 // the formatted string.\r
761 //\r
762 Status = gBS->HandleProtocol (\r
763 Controller,\r
764 &gEfiSimpleNetworkProtocolGuid,\r
765 (VOID **)&Snp\r
766 );\r
767 ASSERT (Status == EFI_SUCCESS);\r
768\r
769 IScsiMacAddrToStr (&Snp->Mode->PermanentAddress, Snp->Mode->HwAddressSize, ConfigFormEntry->MacString);\r
770\r
771 //\r
772 // Get the normal session configuration data.\r
773 //\r
774 BufferSize = sizeof (ConfigFormEntry->SessionConfigData);\r
775 Status = gRT->GetVariable (\r
776 ConfigFormEntry->MacString,\r
777 &gEfiIScsiInitiatorNameProtocolGuid,\r
778 NULL,\r
779 &BufferSize,\r
780 &ConfigFormEntry->SessionConfigData\r
781 );\r
782 if (EFI_ERROR (Status)) {\r
e48e37fc 783 ZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));\r
6a690e23 784 }\r
785 //\r
786 // Get the CHAP authentication configuration data.\r
787 //\r
788 BufferSize = sizeof (ConfigFormEntry->AuthConfigData);\r
789 Status = gRT->GetVariable (\r
790 ConfigFormEntry->MacString,\r
791 &mIScsiCHAPAuthInfoGuid,\r
792 NULL,\r
793 &BufferSize,\r
794 &ConfigFormEntry->AuthConfigData\r
795 );\r
796 if (EFI_ERROR (Status)) {\r
e48e37fc 797 ZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));\r
6a690e23 798 }\r
799 //\r
6c7a807a 800 // Compose the Port string and create a new EFI_STRING_ID.\r
6a690e23 801 //\r
802 UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
9226efe5 803 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);\r
6a690e23 804\r
805 //\r
6c7a807a 806 // Compose the help string of this port and create a new EFI_STRING_ID.\r
6a690e23 807 //\r
808 UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
9226efe5 809 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);\r
6a690e23 810\r
e48e37fc 811 InsertTailList (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
6a690e23 812 mNumberOfIScsiDevices++;\r
813 }\r
814 } else {\r
815 ASSERT (EntryExisted);\r
816\r
817 mNumberOfIScsiDevices--;\r
e48e37fc 818 RemoveEntryList (&ConfigFormEntry->Link);\r
819 gBS->FreePool (ConfigFormEntry);\r
6a690e23 820 }\r
821 //\r
822 // Allocate space for creation of Buffer\r
823 //\r
93e3992d 824 UpdateData.BufferSize = 0x1000;\r
e48e37fc 825 UpdateData.Data = AllocateZeroPool (0x1000);\r
93e3992d 826 UpdateData.Offset = 0;\r
6a690e23 827\r
93e3992d 828 FormIndex = 0;\r
6a690e23 829 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
830 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
831\r
832 CreateGotoOpCode (\r
833 FORMID_DEVICE_FORM,\r
834 ConfigFormEntry->PortTitleToken,\r
835 ConfigFormEntry->PortTitleHelpToken,\r
93e3992d 836 EFI_IFR_FLAG_CALLBACK,\r
69b0882d 837 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex),\r
93e3992d 838 &UpdateData\r
6a690e23 839 );\r
840\r
6a690e23 841 FormIndex++;\r
842 }\r
843\r
93e3992d 844 IfrLibUpdateForm (\r
845 mCallbackInfo->RegisteredHandle,\r
846 &mVendorGuid,\r
847 FORMID_MAIN_FORM,\r
848 DEVICE_ENTRY_LABEL,\r
849 FALSE,\r
850 &UpdateData\r
851 );\r
852\r
e48e37fc 853 gBS->FreePool (UpdateData.Data);\r
6a690e23 854\r
855 return EFI_SUCCESS;\r
856}\r
857\r
12618416 858/**\r
6a690e23 859 Initialize the iSCSI configuration form.\r
860\r
12618416 861 @param DriverBindingHandle[in] The iSCSI driverbinding handle.\r
6a690e23 862\r
12618416 863 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
6a690e23 864\r
12618416 865 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
6a690e23 866\r
12618416 867**/\r
868EFI_STATUS\r
869IScsiConfigFormInit (\r
870 IN EFI_HANDLE DriverBindingHandle\r
871 )\r
6a690e23 872{\r
93e3992d 873 EFI_STATUS Status;\r
874 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
875 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
876 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
877\r
69b0882d 878 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);\r
6a690e23 879 if (EFI_ERROR (Status)) {\r
93e3992d 880 return Status;\r
6a690e23 881 }\r
882\r
e48e37fc 883 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
6a690e23 884 if (CallbackInfo == NULL) {\r
885 return EFI_OUT_OF_RESOURCES;\r
886 }\r
887\r
f2a94e25 888 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
93e3992d 889 CallbackInfo->HiiDatabase = HiiDatabase;\r
f2a94e25 890 CallbackInfo->Current = NULL;\r
6a690e23 891\r
93e3992d 892 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
893 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
894 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
6a690e23 895\r
69b0882d 896 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);\r
93e3992d 897 if (EFI_ERROR (Status)) {\r
f2a94e25 898 FreePool(CallbackInfo);\r
93e3992d 899 return Status;\r
900 }\r
901\r
902 //\r
903 // Create driver handle used by HII database\r
904 //\r
905 Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);\r
906 if (EFI_ERROR (Status)) {\r
f2a94e25 907 FreePool(CallbackInfo);\r
93e3992d 908 return Status;\r
909 }\r
910 \r
6a690e23 911 //\r
93e3992d 912 // Install Config Access protocol to driver handle\r
6a690e23 913 //\r
914 Status = gBS->InstallProtocolInterface (\r
93e3992d 915 &CallbackInfo->DriverHandle,\r
916 &gEfiHiiConfigAccessProtocolGuid,\r
6a690e23 917 EFI_NATIVE_INTERFACE,\r
93e3992d 918 &CallbackInfo->ConfigAccess\r
6a690e23 919 );\r
6a690e23 920 ASSERT_EFI_ERROR (Status);\r
93e3992d 921 \r
6a690e23 922 //\r
93e3992d 923 // Publish our HII data\r
6a690e23 924 //\r
9226efe5 925 PackageList = HiiLibPreparePackageList (2, &mVendorGuid, IScsiDxeStrings, IScsiConfigDxeBin);\r
93e3992d 926 ASSERT (PackageList != NULL);\r
927 \r
928 Status = HiiDatabase->NewPackageList (\r
929 HiiDatabase,\r
930 PackageList,\r
931 CallbackInfo->DriverHandle,\r
932 &CallbackInfo->RegisteredHandle\r
933 );\r
f2a94e25 934 FreePool (PackageList);\r
93e3992d 935 if (EFI_ERROR (Status)) {\r
f2a94e25 936 FreePool(CallbackInfo);\r
93e3992d 937 return Status;\r
6a690e23 938 }\r
939\r
93e3992d 940 mCallbackInfo = CallbackInfo;\r
6a690e23 941\r
942 return Status;\r
943}\r
944\r
12618416 945/**\r
6a690e23 946 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
947 device configuration entries, uninstall the form callback protocol and\r
948 free the resources used.\r
949\r
12618416 950 @param DriverBindingHandle[in] The iSCSI driverbinding handle.\r
6a690e23 951\r
12618416 952 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
6a690e23 953\r
12618416 954 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
6a690e23 955\r
12618416 956**/\r
957EFI_STATUS\r
958IScsiConfigFormUnload (\r
959 IN EFI_HANDLE DriverBindingHandle\r
960 )\r
6a690e23 961{\r
962 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
6a690e23 963\r
e48e37fc 964 while (!IsListEmpty (&mIScsiConfigFormList)) {\r
6a690e23 965 //\r
966 // Uninstall the device forms as the iSCSI driver instance may fail to\r
967 // control the controller but still install the device configuration form.\r
968 // In such case, upon driver unloading, the driver instance's driverbinding.\r
969 // stop () won't be called, so we have to take this chance here to uninstall\r
970 // the device form.\r
971 //\r
972 ConfigFormEntry = NET_LIST_USER_STRUCT (mIScsiConfigFormList.ForwardLink, ISCSI_CONFIG_FORM_ENTRY, Link);\r
973 IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
974 }\r
975\r
6a690e23 976 //\r
93e3992d 977 // Remove HII package list\r
6a690e23 978 //\r
93e3992d 979 mCallbackInfo->HiiDatabase->RemovePackageList (\r
980 mCallbackInfo->HiiDatabase,\r
981 mCallbackInfo->RegisteredHandle\r
982 );\r
6a690e23 983\r
984 //\r
93e3992d 985 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
6a690e23 986 //\r
987 gBS->UninstallProtocolInterface (\r
93e3992d 988 mCallbackInfo->DriverHandle,\r
989 &gEfiHiiConfigAccessProtocolGuid,\r
990 &mCallbackInfo->ConfigAccess\r
6a690e23 991 );\r
93e3992d 992 HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);\r
6a690e23 993\r
e48e37fc 994 gBS->FreePool (mCallbackInfo);\r
6a690e23 995\r
996 return EFI_SUCCESS;\r
997}\r