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