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