]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
update file header
[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
8d00a0f1 338 if (Request == NULL) {\r
339 return EFI_NOT_FOUND;\r
340 }\r
341\r
6a690e23 342 if (!mIScsiDeviceListUpdated) {\r
343 //\r
344 // Update the device list.\r
345 //\r
346 IScsiUpdateDeviceList ();\r
347 mIScsiDeviceListUpdated = TRUE;\r
348 }\r
349\r
93e3992d 350 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
351 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
352 ASSERT (IfrNvData != NULL);\r
353 if (Private->Current != NULL) {\r
354 IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
355 }\r
6a690e23 356\r
93e3992d 357 BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
6a690e23 358 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
359 if (EFI_ERROR (Status)) {\r
360 IfrNvData->InitiatorName[0] = L'\0';\r
361 } else {\r
362 IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
363 }\r
364\r
93e3992d 365 //\r
366 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
367 //\r
368 HiiConfigRouting = Private->ConfigRouting;\r
369 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
370 Status = HiiConfigRouting->BlockToConfig (\r
371 HiiConfigRouting,\r
372 Request,\r
373 (UINT8 *) IfrNvData,\r
374 BufferSize,\r
375 Results,\r
376 Progress\r
377 );\r
e48e37fc 378 gBS->FreePool (IfrNvData);\r
93e3992d 379 return Status;\r
6a690e23 380}\r
381\r
12618416 382/**\r
383 This function processes the results of changes in configuration.\r
384\r
385 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
386\r
387 @param Configuration[in] A null-terminated Unicode string in <ConfigResp> format.\r
388\r
389 @param Progress[out] A pointer to a string filled in with the offset of the most\r
390 recent '&' before the first failing name/value pair (or the\r
391 beginning of the string if the failure is in the first\r
392 name/value pair) or the terminating NULL if all was successful.\r
393\r
394 @retval EFI_SUCCESS The Results is processed successfully.\r
395\r
396 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
397\r
398 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
399\r
400**/\r
6a690e23 401EFI_STATUS\r
402EFIAPI\r
93e3992d 403IScsiFormRouteConfig (\r
404 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
405 IN CONST EFI_STRING Configuration,\r
406 OUT EFI_STRING *Progress\r
6a690e23 407 )\r
12618416 408{\r
409 return EFI_SUCCESS;\r
410}\r
6a690e23 411\r
12618416 412/**\r
413 This function processes the results of changes in configuration.\r
6a690e23 414\r
12618416 415 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
6a690e23 416\r
12618416 417 @param Action[in] Specifies the type of action taken by the browser.\r
6a690e23 418\r
12618416 419 @param QuestionId[in] A unique value which is sent to the original exporting driver\r
420 so that it can identify the type of data to expect.\r
421\r
422 @param Type[in] The type of value for the question.\r
423\r
424 @param Value[in] A pointer to the data being sent to the original exporting driver.\r
425\r
426 @param ActionRequest[out] On return, points to the action requested by the callback function.\r
427\r
428 @retval EFI_SUCCESS The callback successfully handled the action.\r
429\r
430 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data.\r
6a690e23 431\r
12618416 432 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
433\r
434 @retval EFI_UNSUPPORTED The specified Action is not supported by the callback.\r
435\r
436**/\r
93e3992d 437EFI_STATUS\r
438EFIAPI\r
439IScsiFormCallback (\r
440 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
441 IN EFI_BROWSER_ACTION Action,\r
442 IN EFI_QUESTION_ID KeyValue,\r
443 IN UINT8 Type,\r
444 IN EFI_IFR_TYPE_VALUE *Value,\r
445 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
446 )\r
6a690e23 447{\r
448 ISCSI_FORM_CALLBACK_INFO *Private;\r
449 UINTN BufferSize;\r
450 CHAR8 IScsiName[ISCSI_NAME_IFR_MAX_SIZE];\r
451 CHAR16 PortString[128];\r
452 CHAR8 Ip4String[IP4_STR_MAX_SIZE];\r
453 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
454 UINT64 Lun;\r
6c7a807a 455 EFI_STRING_ID DeviceFormTitleToken;\r
6a690e23 456 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
457 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
458 EFI_IP_ADDRESS HostIp;\r
459 EFI_IP_ADDRESS SubnetMask;\r
460 EFI_IP_ADDRESS Gateway;\r
461 EFI_STATUS Status;\r
462\r
463 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
93e3992d 464\r
465 //\r
466 // Retrive uncommitted data from Browser\r
467 //\r
468 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
469 IfrNvData = AllocateZeroPool (BufferSize);\r
470 ASSERT (IfrNvData != NULL);\r
471 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) IfrNvData);\r
472 if (EFI_ERROR (Status)) {\r
473 gBS->FreePool (IfrNvData);\r
474 return Status;\r
475 }\r
6a690e23 476\r
477 switch (KeyValue) {\r
478 case KEY_INITIATOR_NAME:\r
479 IScsiUnicodeStrToAsciiStr (IfrNvData->InitiatorName, IScsiName);\r
480 BufferSize = AsciiStrLen (IScsiName) + 1;\r
481\r
482 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
483 if (EFI_ERROR (Status)) {\r
484 PopUpInvalidNotify (L"Invalid iSCSI Name!");\r
485 }\r
486\r
487 break;\r
488\r
489 case KEY_LOCAL_IP:\r
490 IScsiUnicodeStrToAsciiStr (IfrNvData->LocalIp, Ip4String);\r
491 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
492 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
493 PopUpInvalidNotify (L"Invalid IP address!");\r
494 Status = EFI_INVALID_PARAMETER;\r
495 } else {\r
e48e37fc 496 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 497 }\r
498\r
499 break;\r
500\r
501 case KEY_SUBNET_MASK:\r
502 IScsiUnicodeStrToAsciiStr (IfrNvData->SubnetMask, Ip4String);\r
503 Status = IScsiAsciiStrToIp (Ip4String, &SubnetMask.v4);\r
504 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
505 PopUpInvalidNotify (L"Invalid Subnet Mask!");\r
506 Status = EFI_INVALID_PARAMETER;\r
507 } else {\r
e48e37fc 508 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
6a690e23 509 }\r
510\r
511 break;\r
512\r
513 case KEY_GATE_WAY:\r
514 IScsiUnicodeStrToAsciiStr (IfrNvData->Gateway, Ip4String);\r
515 Status = IScsiAsciiStrToIp (Ip4String, &Gateway.v4);\r
516 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !Ip4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
517 PopUpInvalidNotify (L"Invalid Gateway!");\r
518 Status = EFI_INVALID_PARAMETER;\r
519 } else {\r
e48e37fc 520 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
6a690e23 521 }\r
522\r
523 break;\r
524\r
525 case KEY_TARGET_IP:\r
526 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetIp, Ip4String);\r
527 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
528 if (EFI_ERROR (Status) || !Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
529 PopUpInvalidNotify (L"Invalid IP address!");\r
530 Status = EFI_INVALID_PARAMETER;\r
531 } else {\r
e48e37fc 532 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
6a690e23 533 }\r
534\r
535 break;\r
536\r
537 case KEY_TARGET_NAME:\r
538 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetName, IScsiName);\r
539 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
540 if (EFI_ERROR (Status)) {\r
541 PopUpInvalidNotify (L"Invalid iSCSI Name!");\r
542 } else {\r
543 AsciiStrCpy (Private->Current->SessionConfigData.TargetName, IScsiName);\r
544 }\r
545\r
546 break;\r
547\r
548 case KEY_DHCP_ENABLE:\r
549 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
550 IfrNvData->TargetInfoFromDhcp = 0;\r
551 }\r
552\r
553 break;\r
554\r
555 case KEY_BOOT_LUN:\r
556 IScsiUnicodeStrToAsciiStr (IfrNvData->BootLun, LunString);\r
557 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
558 if (EFI_ERROR (Status)) {\r
559 PopUpInvalidNotify (L"Invalid LUN string!");\r
560 } else {\r
e48e37fc 561 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
6a690e23 562 }\r
563\r
564 break;\r
565\r
566 case KEY_CHAP_NAME:\r
567 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPName, Private->Current->AuthConfigData.CHAPName);\r
568 break;\r
569\r
570 case KEY_CHAP_SECRET:\r
571 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPSecret, Private->Current->AuthConfigData.CHAPSecret);\r
572 break;\r
573\r
574 case KEY_REVERSE_CHAP_NAME:\r
575 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPName, Private->Current->AuthConfigData.ReverseCHAPName);\r
576 break;\r
577\r
578 case KEY_REVERSE_CHAP_SECRET:\r
579 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPSecret, Private->Current->AuthConfigData.ReverseCHAPSecret);\r
580 break;\r
581\r
582 case KEY_SAVE_CHANGES:\r
583 //\r
584 // First, update those fields which don't have INTERACTIVE set.\r
585 //\r
586 Private->Current->SessionConfigData.Enabled = IfrNvData->Enabled;\r
587 Private->Current->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
588 Private->Current->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
589 if (Private->Current->SessionConfigData.TargetPort == 0) {\r
590 Private->Current->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
591 }\r
592\r
593 Private->Current->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
594 Private->Current->AuthConfigData.CHAPType = IfrNvData->CHAPType;\r
595\r
596 //\r
597 // Only do full parameter validation if iSCSI is enabled on this device.\r
598 //\r
599 if (Private->Current->SessionConfigData.Enabled) {\r
600 //\r
601 // Validate the address configuration of the Initiator if DHCP isn't\r
602 // deployed.\r
603 //\r
604 if (!Private->Current->SessionConfigData.InitiatorInfoFromDhcp) {\r
e48e37fc 605 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
606 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
607 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
6a690e23 608\r
609 if ((Gateway.Addr[0] != 0)) {\r
610 if (SubnetMask.Addr[0] == 0) {\r
611 PopUpInvalidNotify (L"Gateway address is set but subnet mask is zero.");\r
612 Status = EFI_INVALID_PARAMETER;\r
613 break;\r
614 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
615 PopUpInvalidNotify (L"Local IP and Gateway are not in the same subnet.");\r
616 Status = EFI_INVALID_PARAMETER;\r
617 break;\r
618 }\r
619 }\r
620 }\r
621 //\r
622 // Validate target configuration if DHCP isn't deployed.\r
623 //\r
624 if (!Private->Current->SessionConfigData.TargetInfoFromDhcp) {\r
e48e37fc 625 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
6a690e23 626 if (!Ip4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
627 PopUpInvalidNotify (L"Target IP is invalid!");\r
628 Status = EFI_INVALID_PARAMETER;\r
629 break;\r
630 }\r
631 }\r
632\r
633 if (IfrNvData->CHAPType != ISCSI_CHAP_NONE) {\r
634 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
635 PopUpInvalidNotify (L"CHAP Name or CHAP Secret is invalid!");\r
636 Status = EFI_INVALID_PARAMETER;\r
637 break;\r
638 }\r
639\r
640 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
641 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
642 ) {\r
643 PopUpInvalidNotify (L"Reverse CHAP Name or Reverse CHAP Secret is invalid!");\r
644 Status = EFI_INVALID_PARAMETER;\r
645 break;\r
646 }\r
647 }\r
648 }\r
649\r
650 BufferSize = sizeof (Private->Current->SessionConfigData);\r
651 gRT->SetVariable (\r
652 Private->Current->MacString,\r
653 &gEfiIScsiInitiatorNameProtocolGuid,\r
654 ISCSI_CONFIG_VAR_ATTR,\r
655 BufferSize,\r
656 &Private->Current->SessionConfigData\r
657 );\r
658\r
659 BufferSize = sizeof (Private->Current->AuthConfigData);\r
660 gRT->SetVariable (\r
661 Private->Current->MacString,\r
662 &mIScsiCHAPAuthInfoGuid,\r
663 ISCSI_CONFIG_VAR_ATTR,\r
664 BufferSize,\r
665 &Private->Current->AuthConfigData\r
666 );\r
93e3992d 667 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
6a690e23 668 break;\r
669\r
670 default:\r
671 if ((KeyValue >= KEY_DEVICE_ENTRY_BASE) && (KeyValue < (mNumberOfIScsiDevices + KEY_DEVICE_ENTRY_BASE))) {\r
672 //\r
673 // In case goto the device configuration form, update the device form title.\r
674 //\r
675 ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (KeyValue - KEY_DEVICE_ENTRY_BASE));\r
676 ASSERT (ConfigFormEntry != NULL);\r
677\r
93e3992d 678 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
6c7a807a 679 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;\r
9226efe5 680 HiiLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);\r
6a690e23 681\r
682 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
683\r
684 Private->Current = ConfigFormEntry;\r
685 }\r
686\r
687 break;\r
688 }\r
689\r
93e3992d 690 if (!EFI_ERROR (Status)) {\r
691 //\r
692 // Pass changed uncommitted data back to Form Browser\r
693 //\r
694 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
695 Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);\r
696 }\r
697\r
e48e37fc 698 gBS->FreePool (IfrNvData);\r
6a690e23 699 return Status;\r
700}\r
701\r
12618416 702/**\r
6a690e23 703 Updates the iSCSI configuration form to add/delete an entry for the iSCSI\r
704 device specified by the Controller.\r
705\r
12618416 706 @param DriverBindingHandle[in] The driverbinding handle.\r
707\r
708 @param Controller[in] The controller handle of the iSCSI device.\r
6a690e23 709\r
12618416 710 @param AddForm[in] Whether to add or delete a form entry.\r
6a690e23 711\r
12618416 712 @retval EFI_SUCCESS The iSCSI configuration form is updated.\r
6a690e23 713\r
12618416 714 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
6a690e23 715\r
12618416 716**/\r
717EFI_STATUS\r
718IScsiConfigUpdateForm (\r
719 IN EFI_HANDLE DriverBindingHandle,\r
720 IN EFI_HANDLE Controller,\r
721 IN BOOLEAN AddForm\r
722 )\r
6a690e23 723{\r
e48e37fc 724 LIST_ENTRY *Entry;\r
6a690e23 725 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
726 BOOLEAN EntryExisted;\r
6a690e23 727 EFI_STATUS Status;\r
93e3992d 728 EFI_HII_UPDATE_DATA UpdateData;\r
6a690e23 729 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
730 CHAR16 PortString[128];\r
731 UINT16 FormIndex;\r
732 UINTN BufferSize;\r
733\r
6a690e23 734\r
735 ConfigFormEntry = NULL;\r
736 EntryExisted = FALSE;\r
737\r
738 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
739 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
740\r
741 if (ConfigFormEntry->Controller == Controller) {\r
742 EntryExisted = TRUE;\r
743 break;\r
744 }\r
745 }\r
746\r
747 if (AddForm) {\r
748 if (EntryExisted) {\r
749 return EFI_SUCCESS;\r
750 } else {\r
751 //\r
752 // Add a new form.\r
753 //\r
e48e37fc 754 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
6a690e23 755 if (ConfigFormEntry == NULL) {\r
756 return EFI_OUT_OF_RESOURCES;\r
757 }\r
758\r
e48e37fc 759 InitializeListHead (&ConfigFormEntry->Link);\r
6a690e23 760 ConfigFormEntry->Controller = Controller;\r
761\r
762 //\r
763 // Get the simple network protocol and convert the MAC address into\r
764 // the formatted string.\r
765 //\r
766 Status = gBS->HandleProtocol (\r
767 Controller,\r
768 &gEfiSimpleNetworkProtocolGuid,\r
769 (VOID **)&Snp\r
770 );\r
771 ASSERT (Status == EFI_SUCCESS);\r
772\r
773 IScsiMacAddrToStr (&Snp->Mode->PermanentAddress, Snp->Mode->HwAddressSize, ConfigFormEntry->MacString);\r
774\r
775 //\r
776 // Get the normal session configuration data.\r
777 //\r
778 BufferSize = sizeof (ConfigFormEntry->SessionConfigData);\r
779 Status = gRT->GetVariable (\r
780 ConfigFormEntry->MacString,\r
781 &gEfiIScsiInitiatorNameProtocolGuid,\r
782 NULL,\r
783 &BufferSize,\r
784 &ConfigFormEntry->SessionConfigData\r
785 );\r
786 if (EFI_ERROR (Status)) {\r
e48e37fc 787 ZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));\r
6a690e23 788 }\r
789 //\r
790 // Get the CHAP authentication configuration data.\r
791 //\r
792 BufferSize = sizeof (ConfigFormEntry->AuthConfigData);\r
793 Status = gRT->GetVariable (\r
794 ConfigFormEntry->MacString,\r
795 &mIScsiCHAPAuthInfoGuid,\r
796 NULL,\r
797 &BufferSize,\r
798 &ConfigFormEntry->AuthConfigData\r
799 );\r
800 if (EFI_ERROR (Status)) {\r
e48e37fc 801 ZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));\r
6a690e23 802 }\r
803 //\r
6c7a807a 804 // Compose the Port string and create a new EFI_STRING_ID.\r
6a690e23 805 //\r
806 UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
9226efe5 807 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);\r
6a690e23 808\r
809 //\r
6c7a807a 810 // Compose the help string of this port and create a new EFI_STRING_ID.\r
6a690e23 811 //\r
812 UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
9226efe5 813 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);\r
6a690e23 814\r
e48e37fc 815 InsertTailList (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
6a690e23 816 mNumberOfIScsiDevices++;\r
817 }\r
818 } else {\r
819 ASSERT (EntryExisted);\r
820\r
821 mNumberOfIScsiDevices--;\r
e48e37fc 822 RemoveEntryList (&ConfigFormEntry->Link);\r
823 gBS->FreePool (ConfigFormEntry);\r
6a690e23 824 }\r
825 //\r
826 // Allocate space for creation of Buffer\r
827 //\r
93e3992d 828 UpdateData.BufferSize = 0x1000;\r
e48e37fc 829 UpdateData.Data = AllocateZeroPool (0x1000);\r
93e3992d 830 UpdateData.Offset = 0;\r
6a690e23 831\r
93e3992d 832 FormIndex = 0;\r
6a690e23 833 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
834 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
835\r
836 CreateGotoOpCode (\r
837 FORMID_DEVICE_FORM,\r
838 ConfigFormEntry->PortTitleToken,\r
839 ConfigFormEntry->PortTitleHelpToken,\r
93e3992d 840 EFI_IFR_FLAG_CALLBACK,\r
69b0882d 841 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex),\r
93e3992d 842 &UpdateData\r
6a690e23 843 );\r
844\r
6a690e23 845 FormIndex++;\r
846 }\r
847\r
93e3992d 848 IfrLibUpdateForm (\r
849 mCallbackInfo->RegisteredHandle,\r
850 &mVendorGuid,\r
851 FORMID_MAIN_FORM,\r
852 DEVICE_ENTRY_LABEL,\r
853 FALSE,\r
854 &UpdateData\r
855 );\r
856\r
e48e37fc 857 gBS->FreePool (UpdateData.Data);\r
6a690e23 858\r
859 return EFI_SUCCESS;\r
860}\r
861\r
12618416 862/**\r
6a690e23 863 Initialize the iSCSI configuration form.\r
864\r
12618416 865 @param DriverBindingHandle[in] The iSCSI driverbinding handle.\r
6a690e23 866\r
12618416 867 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
6a690e23 868\r
12618416 869 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
6a690e23 870\r
12618416 871**/\r
872EFI_STATUS\r
873IScsiConfigFormInit (\r
874 IN EFI_HANDLE DriverBindingHandle\r
875 )\r
6a690e23 876{\r
93e3992d 877 EFI_STATUS Status;\r
878 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
879 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
880 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
881\r
69b0882d 882 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);\r
6a690e23 883 if (EFI_ERROR (Status)) {\r
93e3992d 884 return Status;\r
6a690e23 885 }\r
886\r
e48e37fc 887 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
6a690e23 888 if (CallbackInfo == NULL) {\r
889 return EFI_OUT_OF_RESOURCES;\r
890 }\r
891\r
f2a94e25 892 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
93e3992d 893 CallbackInfo->HiiDatabase = HiiDatabase;\r
f2a94e25 894 CallbackInfo->Current = NULL;\r
6a690e23 895\r
93e3992d 896 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
897 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
898 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
6a690e23 899\r
69b0882d 900 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);\r
93e3992d 901 if (EFI_ERROR (Status)) {\r
f2a94e25 902 FreePool(CallbackInfo);\r
93e3992d 903 return Status;\r
904 }\r
905\r
906 //\r
907 // Create driver handle used by HII database\r
908 //\r
909 Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);\r
910 if (EFI_ERROR (Status)) {\r
f2a94e25 911 FreePool(CallbackInfo);\r
93e3992d 912 return Status;\r
913 }\r
914 \r
6a690e23 915 //\r
93e3992d 916 // Install Config Access protocol to driver handle\r
6a690e23 917 //\r
918 Status = gBS->InstallProtocolInterface (\r
93e3992d 919 &CallbackInfo->DriverHandle,\r
920 &gEfiHiiConfigAccessProtocolGuid,\r
6a690e23 921 EFI_NATIVE_INTERFACE,\r
93e3992d 922 &CallbackInfo->ConfigAccess\r
6a690e23 923 );\r
6a690e23 924 ASSERT_EFI_ERROR (Status);\r
93e3992d 925 \r
6a690e23 926 //\r
93e3992d 927 // Publish our HII data\r
6a690e23 928 //\r
9226efe5 929 PackageList = HiiLibPreparePackageList (2, &mVendorGuid, IScsiDxeStrings, IScsiConfigDxeBin);\r
93e3992d 930 ASSERT (PackageList != NULL);\r
931 \r
932 Status = HiiDatabase->NewPackageList (\r
933 HiiDatabase,\r
934 PackageList,\r
935 CallbackInfo->DriverHandle,\r
936 &CallbackInfo->RegisteredHandle\r
937 );\r
f2a94e25 938 FreePool (PackageList);\r
93e3992d 939 if (EFI_ERROR (Status)) {\r
f2a94e25 940 FreePool(CallbackInfo);\r
93e3992d 941 return Status;\r
6a690e23 942 }\r
943\r
93e3992d 944 mCallbackInfo = CallbackInfo;\r
6a690e23 945\r
946 return Status;\r
947}\r
948\r
12618416 949/**\r
6a690e23 950 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
951 device configuration entries, uninstall the form callback protocol and\r
952 free the resources used.\r
953\r
12618416 954 @param DriverBindingHandle[in] The iSCSI driverbinding handle.\r
6a690e23 955\r
12618416 956 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
6a690e23 957\r
12618416 958 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
6a690e23 959\r
12618416 960**/\r
961EFI_STATUS\r
962IScsiConfigFormUnload (\r
963 IN EFI_HANDLE DriverBindingHandle\r
964 )\r
6a690e23 965{\r
966 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
6a690e23 967\r
e48e37fc 968 while (!IsListEmpty (&mIScsiConfigFormList)) {\r
6a690e23 969 //\r
970 // Uninstall the device forms as the iSCSI driver instance may fail to\r
971 // control the controller but still install the device configuration form.\r
972 // In such case, upon driver unloading, the driver instance's driverbinding.\r
973 // stop () won't be called, so we have to take this chance here to uninstall\r
974 // the device form.\r
975 //\r
976 ConfigFormEntry = NET_LIST_USER_STRUCT (mIScsiConfigFormList.ForwardLink, ISCSI_CONFIG_FORM_ENTRY, Link);\r
977 IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
978 }\r
979\r
6a690e23 980 //\r
93e3992d 981 // Remove HII package list\r
6a690e23 982 //\r
93e3992d 983 mCallbackInfo->HiiDatabase->RemovePackageList (\r
984 mCallbackInfo->HiiDatabase,\r
985 mCallbackInfo->RegisteredHandle\r
986 );\r
6a690e23 987\r
988 //\r
93e3992d 989 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
6a690e23 990 //\r
991 gBS->UninstallProtocolInterface (\r
93e3992d 992 mCallbackInfo->DriverHandle,\r
993 &gEfiHiiConfigAccessProtocolGuid,\r
994 &mCallbackInfo->ConfigAccess\r
6a690e23 995 );\r
93e3992d 996 HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);\r
6a690e23 997\r
e48e37fc 998 gBS->FreePool (mCallbackInfo);\r
6a690e23 999\r
1000 return EFI_SUCCESS;\r
1001}\r