]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/iScsi/IScsiConfig.c
UEFI HII: Merge UEFI HII support changes from branch.
[mirror_edk2.git] / MdeModulePkg / Universal / iScsi / IScsiConfig.c
CommitLineData
6a690e23 1/*++\r
2\r
3Copyright (c) 2007 Intel Corporation. All rights reserved\r
4This software and associated documentation (if any) is furnished\r
5under a license and may only be used or copied in accordance\r
6with the terms of the license. Except as permitted by such\r
7license, no part of this software or documentation may be\r
8reproduced, stored in a retrieval system, or transmitted in any\r
9form or by any means without the express written consent of\r
10Intel Corporation.\r
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
22EFI_GUID mVendorGuid = ISCSI_CONFIG_GUID;\r
23BOOLEAN mIScsiDeviceListUpdated = FALSE;\r
24UINTN mNumberOfIScsiDevices = 0;\r
93e3992d 25ISCSI_FORM_CALLBACK_INFO *mCallbackInfo;\r
6a690e23 26\r
27NET_LIST_ENTRY mIScsiConfigFormList = {\r
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
141 DeviceList = (ISCSI_DEVICE_LIST *) NetAllocatePool (DataSize);\r
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
171 NetCopyMem (&TempMacInfo, CurMacInfo, sizeof (ISCSI_MAC_INFO));\r
172 NetCopyMem (CurMacInfo, &DeviceList->MacInfo[LastDeviceIndex], sizeof (ISCSI_MAC_INFO));\r
173 NetCopyMem (&DeviceList->MacInfo[LastDeviceIndex], &TempMacInfo, sizeof (ISCSI_MAC_INFO));\r
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
195 NetFreePool (DeviceList);\r
196 } else if (Status != EFI_NOT_FOUND) {\r
197 NetFreePool (Handles);\r
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
204 DeviceList = (ISCSI_DEVICE_LIST *) NetAllocatePool (DeviceListSize);\r
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
212 NetCopyMem (&CurMacInfo->Mac, &Mode->PermanentAddress, Mode->HwAddressSize);\r
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
224 NetFreePool (DeviceList);\r
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
251 NET_LIST_ENTRY *Entry;\r
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
405 NetFreePool (IfrNvData);\r
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
519 NetCopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
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
531 NetCopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
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
543 NetCopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
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
555 NetCopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
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
584 NetCopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
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
628 NetCopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
629 NetCopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
630 NetCopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
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
648 NetCopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
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
93e3992d 703 IfrLibSetString (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
721 NetFreePool (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
752 NET_LIST_ENTRY *Entry;\r
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
782 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) NetAllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
783 if (ConfigFormEntry == NULL) {\r
784 return EFI_OUT_OF_RESOURCES;\r
785 }\r
786\r
787 NetListInit (&ConfigFormEntry->Link);\r
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
815 NetZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));\r
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
829 NetZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));\r
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
93e3992d 835 IfrLibNewString (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
93e3992d 841 IfrLibNewString (mCallbackInfo->RegisteredHandle, &ConfigFormEntry->PortTitleHelpToken, PortString);\r
6a690e23 842\r
843 NetListInsertTail (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
844 mNumberOfIScsiDevices++;\r
845 }\r
846 } else {\r
847 ASSERT (EntryExisted);\r
848\r
849 mNumberOfIScsiDevices--;\r
850 NetListRemoveEntry (&ConfigFormEntry->Link);\r
851 NetFreePool (ConfigFormEntry);\r
852 }\r
853 //\r
854 // Allocate space for creation of Buffer\r
855 //\r
93e3992d 856 UpdateData.BufferSize = 0x1000;\r
857 UpdateData.Data = NetAllocateZeroPool (0x1000);\r
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
869 KEY_DEVICE_ENTRY_BASE + FormIndex,\r
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
885 NetFreePool (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
916 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, &HiiDatabase);\r
6a690e23 917 if (EFI_ERROR (Status)) {\r
93e3992d 918 return Status;\r
6a690e23 919 }\r
920\r
921 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) NetAllocatePool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
922 if (CallbackInfo == NULL) {\r
923 return EFI_OUT_OF_RESOURCES;\r
924 }\r
925\r
926 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
93e3992d 927 CallbackInfo->HiiDatabase = HiiDatabase;\r
6a690e23 928 CallbackInfo->Current = NULL;\r
929\r
93e3992d 930 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
931 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
932 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
6a690e23 933\r
93e3992d 934 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, &CallbackInfo->ConfigRouting);\r
935 if (EFI_ERROR (Status)) {\r
936 return Status;\r
937 }\r
938\r
939 //\r
940 // Create driver handle used by HII database\r
941 //\r
942 Status = HiiLibCreateHiiDriverHandle (&CallbackInfo->DriverHandle);\r
943 if (EFI_ERROR (Status)) {\r
944 return Status;\r
945 }\r
946 \r
6a690e23 947 //\r
93e3992d 948 // Install Config Access protocol to driver handle\r
6a690e23 949 //\r
950 Status = gBS->InstallProtocolInterface (\r
93e3992d 951 &CallbackInfo->DriverHandle,\r
952 &gEfiHiiConfigAccessProtocolGuid,\r
6a690e23 953 EFI_NATIVE_INTERFACE,\r
93e3992d 954 &CallbackInfo->ConfigAccess\r
6a690e23 955 );\r
6a690e23 956 ASSERT_EFI_ERROR (Status);\r
93e3992d 957 \r
6a690e23 958 //\r
93e3992d 959 // Publish our HII data\r
6a690e23 960 //\r
93e3992d 961 PackageList = PreparePackageList (2, &mVendorGuid, iSCSIStrings, IScsiConfigDxeBin);\r
962 ASSERT (PackageList != NULL);\r
963 \r
964 Status = HiiDatabase->NewPackageList (\r
965 HiiDatabase,\r
966 PackageList,\r
967 CallbackInfo->DriverHandle,\r
968 &CallbackInfo->RegisteredHandle\r
969 );\r
970 NetFreePool (PackageList);\r
971 if (EFI_ERROR (Status)) {\r
972 return Status;\r
6a690e23 973 }\r
974\r
93e3992d 975 mCallbackInfo = CallbackInfo;\r
6a690e23 976\r
977 return Status;\r
978}\r
979\r
980EFI_STATUS\r
981IScsiConfigFormUnload (\r
982 IN EFI_HANDLE DriverBindingHandle\r
983 )\r
984/*++\r
985\r
986Routine Description:\r
987\r
988 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
989 device configuration entries, uninstall the form callback protocol and\r
990 free the resources used.\r
991\r
992Arguments:\r
993\r
994 DriverBindingHandle - The iSCSI driverbinding handle.\r
995\r
996Returns:\r
997\r
998 EFI_SUCCESS - The iSCSI configuration form is unloaded.\r
999 EFI_OUT_OF_RESOURCES - Failed to allocate memory.\r
1000\r
1001--*/\r
1002{\r
1003 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
6a690e23 1004\r
1005 while (!NetListIsEmpty (&mIScsiConfigFormList)) {\r
1006 //\r
1007 // Uninstall the device forms as the iSCSI driver instance may fail to\r
1008 // control the controller but still install the device configuration form.\r
1009 // In such case, upon driver unloading, the driver instance's driverbinding.\r
1010 // stop () won't be called, so we have to take this chance here to uninstall\r
1011 // the device form.\r
1012 //\r
1013 ConfigFormEntry = NET_LIST_USER_STRUCT (mIScsiConfigFormList.ForwardLink, ISCSI_CONFIG_FORM_ENTRY, Link);\r
1014 IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
1015 }\r
1016\r
6a690e23 1017 //\r
93e3992d 1018 // Remove HII package list\r
6a690e23 1019 //\r
93e3992d 1020 mCallbackInfo->HiiDatabase->RemovePackageList (\r
1021 mCallbackInfo->HiiDatabase,\r
1022 mCallbackInfo->RegisteredHandle\r
1023 );\r
6a690e23 1024\r
1025 //\r
93e3992d 1026 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
6a690e23 1027 //\r
1028 gBS->UninstallProtocolInterface (\r
93e3992d 1029 mCallbackInfo->DriverHandle,\r
1030 &gEfiHiiConfigAccessProtocolGuid,\r
1031 &mCallbackInfo->ConfigAccess\r
6a690e23 1032 );\r
93e3992d 1033 HiiLibDestroyHiiDriverHandle (mCallbackInfo->DriverHandle);\r
6a690e23 1034\r
93e3992d 1035 NetFreePool (mCallbackInfo);\r
6a690e23 1036\r
1037 return EFI_SUCCESS;\r
1038}\r