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