]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
update file header
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiConfig.c
... / ...
CommitLineData
1/** @file\r
2 Helper functions for configuring or getting the parameters relating to ISCSI\r
3\r
4Copyright (c) 2004 - 2008, Intel Corporation\r
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
12\r
13Module Name:\r
14\r
15 IScsiConfig.c\r
16\r
17Abstract:\r
18\r
19 Helper functions for configuring or getting the parameters relating to ISCSI\r
20\r
21**/\r
22\r
23#include "IScsiImpl.h"\r
24\r
25EFI_GUID mVendorGuid = ISCSI_CONFIG_GUID;\r
26BOOLEAN mIScsiDeviceListUpdated = FALSE;\r
27UINTN mNumberOfIScsiDevices = 0;\r
28ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;\r
29\r
30LIST_ENTRY mIScsiConfigFormList = {\r
31 &mIScsiConfigFormList,\r
32 &mIScsiConfigFormList\r
33};\r
34\r
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
45VOID\r
46IScsiIpToStr (\r
47 IN EFI_IPv4_ADDRESS *Ip,\r
48 OUT CHAR16 *Str\r
49 )\r
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
54/**\r
55 Pop up an invalid notify which displays the message in Warning.\r
56\r
57 @param Warning[in] The warning message.\r
58\r
59 @retval None.\r
60\r
61**/\r
62VOID\r
63PopUpInvalidNotify (\r
64 IN CHAR16 *Warning\r
65 )\r
66{\r
67 EFI_INPUT_KEY Key;\r
68\r
69 IfrLibCreatePopUp (1, &Key, Warning);\r
70}\r
71\r
72/**\r
73 Update the list of iSCSI devices the iSCSI driver is controlling.\r
74\r
75 @param None.\r
76\r
77 @retval None.\r
78\r
79**/\r
80EFI_STATUS\r
81IScsiUpdateDeviceList (\r
82 VOID\r
83 )\r
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
123 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DataSize);\r
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
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
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
177 gBS->FreePool (DeviceList);\r
178 } else if (Status != EFI_NOT_FOUND) {\r
179 gBS->FreePool (Handles);\r
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
186 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DeviceListSize);\r
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
194 CopyMem (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize);\r
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
206 gBS->FreePool (DeviceList);\r
207 gBS->FreePool (Handles);\r
208\r
209 return Status;\r
210}\r
211\r
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
220ISCSI_CONFIG_FORM_ENTRY *\r
221IScsiGetConfigFormEntryByIndex (\r
222 IN UINT32 Index\r
223 )\r
224{\r
225 UINT32 CurrentIndex;\r
226 LIST_ENTRY *Entry;\r
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
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
254VOID\r
255IScsiConvertDeviceConfigDataToIfrNvData (\r
256 IN ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
257 IN ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
258 )\r
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
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
302\r
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
322EFI_STATUS\r
323EFIAPI\r
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
329 )\r
330{\r
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
337\r
338 if (Request == NULL) {\r
339 return EFI_NOT_FOUND;\r
340 }\r
341\r
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
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
356\r
357 BufferSize = ISCSI_NAME_IFR_MAX_SIZE;\r
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
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
378 gBS->FreePool (IfrNvData);\r
379 return Status;\r
380}\r
381\r
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
401EFI_STATUS\r
402EFIAPI\r
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
407 )\r
408{\r
409 return EFI_SUCCESS;\r
410}\r
411\r
412/**\r
413 This function processes the results of changes in configuration.\r
414\r
415 @param This[in] Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
416\r
417 @param Action[in] Specifies the type of action taken by the browser.\r
418\r
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
431\r
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
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
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
455 EFI_STRING_ID DeviceFormTitleToken;\r
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
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
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
496 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
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
508 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
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
520 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
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
532 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
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
561 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
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
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
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
625 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
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
667 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
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
678 UnicodeSPrint (PortString, (UINTN) 128, L"Port %s", ConfigFormEntry->MacString);\r
679 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;\r
680 HiiLibSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString);\r
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
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
698 gBS->FreePool (IfrNvData);\r
699 return Status;\r
700}\r
701\r
702/**\r
703 Updates the iSCSI configuration form to add/delete an entry for the iSCSI\r
704 device specified by the Controller.\r
705\r
706 @param DriverBindingHandle[in] The driverbinding handle.\r
707\r
708 @param Controller[in] The controller handle of the iSCSI device.\r
709\r
710 @param AddForm[in] Whether to add or delete a form entry.\r
711\r
712 @retval EFI_SUCCESS The iSCSI configuration form is updated.\r
713\r
714 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
715\r
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
723{\r
724 LIST_ENTRY *Entry;\r
725 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
726 BOOLEAN EntryExisted;\r
727 EFI_STATUS Status;\r
728 EFI_HII_UPDATE_DATA UpdateData;\r
729 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
730 CHAR16 PortString[128];\r
731 UINT16 FormIndex;\r
732 UINTN BufferSize;\r
733\r
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
754 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
755 if (ConfigFormEntry == NULL) {\r
756 return EFI_OUT_OF_RESOURCES;\r
757 }\r
758\r
759 InitializeListHead (&ConfigFormEntry->Link);\r
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
787 ZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));\r
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
801 ZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));\r
802 }\r
803 //\r
804 // Compose the Port string and create a new EFI_STRING_ID.\r
805 //\r
806 UnicodeSPrint (PortString, 128, L"Port %s", ConfigFormEntry->MacString);\r
807 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleToken, PortString);\r
808\r
809 //\r
810 // Compose the help string of this port and create a new EFI_STRING_ID.\r
811 //\r
812 UnicodeSPrint (PortString, 128, L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
813 HiiLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);\r
814\r
815 InsertTailList (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
816 mNumberOfIScsiDevices++;\r
817 }\r
818 } else {\r
819 ASSERT (EntryExisted);\r
820\r
821 mNumberOfIScsiDevices--;\r
822 RemoveEntryList (&ConfigFormEntry->Link);\r
823 gBS->FreePool (ConfigFormEntry);\r
824 }\r
825 //\r
826 // Allocate space for creation of Buffer\r
827 //\r
828 UpdateData.BufferSize = 0x1000;\r
829 UpdateData.Data = AllocateZeroPool (0x1000);\r
830 UpdateData.Offset = 0;\r
831\r
832 FormIndex = 0;\r
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
840 EFI_IFR_FLAG_CALLBACK,\r
841 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex),\r
842 &UpdateData\r
843 );\r
844\r
845 FormIndex++;\r
846 }\r
847\r
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
857 gBS->FreePool (UpdateData.Data);\r
858\r
859 return EFI_SUCCESS;\r
860}\r
861\r
862/**\r
863 Initialize the iSCSI configuration form.\r
864\r
865 @param DriverBindingHandle[in] The iSCSI driverbinding handle.\r
866\r
867 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
868\r
869 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
870\r
871**/\r
872EFI_STATUS\r
873IScsiConfigFormInit (\r
874 IN EFI_HANDLE DriverBindingHandle\r
875 )\r
876{\r
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
882 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);\r
883 if (EFI_ERROR (Status)) {\r
884 return Status;\r
885 }\r
886\r
887 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
888 if (CallbackInfo == NULL) {\r
889 return EFI_OUT_OF_RESOURCES;\r
890 }\r
891\r
892 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
893 CallbackInfo->HiiDatabase = HiiDatabase;\r
894 CallbackInfo->Current = NULL;\r
895\r
896 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
897 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
898 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
899\r
900 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);\r
901 if (EFI_ERROR (Status)) {\r
902 FreePool(CallbackInfo);\r
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
911 FreePool(CallbackInfo);\r
912 return Status;\r
913 }\r
914 \r
915 //\r
916 // Install Config Access protocol to driver handle\r
917 //\r
918 Status = gBS->InstallProtocolInterface (\r
919 &CallbackInfo->DriverHandle,\r
920 &gEfiHiiConfigAccessProtocolGuid,\r
921 EFI_NATIVE_INTERFACE,\r
922 &CallbackInfo->ConfigAccess\r
923 );\r
924 ASSERT_EFI_ERROR (Status);\r
925 \r
926 //\r
927 // Publish our HII data\r
928 //\r
929 PackageList = HiiLibPreparePackageList (2, &mVendorGuid, IScsiDxeStrings, IScsiConfigDxeBin);\r
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
938 FreePool (PackageList);\r
939 if (EFI_ERROR (Status)) {\r
940 FreePool(CallbackInfo);\r
941 return Status;\r
942 }\r
943\r
944 mCallbackInfo = CallbackInfo;\r
945\r
946 return Status;\r
947}\r
948\r
949/**\r
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
954 @param DriverBindingHandle[in] The iSCSI driverbinding handle.\r
955\r
956 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
957\r
958 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
959\r
960**/\r
961EFI_STATUS\r
962IScsiConfigFormUnload (\r
963 IN EFI_HANDLE DriverBindingHandle\r
964 )\r
965{\r
966 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
967\r
968 while (!IsListEmpty (&mIScsiConfigFormList)) {\r
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
980 //\r
981 // Remove HII package list\r
982 //\r
983 mCallbackInfo->HiiDatabase->RemovePackageList (\r
984 mCallbackInfo->HiiDatabase,\r
985 mCallbackInfo->RegisteredHandle\r
986 );\r
987\r
988 //\r
989 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
990 //\r
991 gBS->UninstallProtocolInterface (\r
992 mCallbackInfo->DriverHandle,\r
993 &gEfiHiiConfigAccessProtocolGuid,\r
994 &mCallbackInfo->ConfigAccess\r
995 );\r
996 HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);\r
997\r
998 gBS->FreePool (mCallbackInfo);\r
999\r
1000 return EFI_SUCCESS;\r
1001}\r