]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/IScsiDxe/IScsiConfig.c
Refine code to make it more safely.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / IScsiDxe / IScsiConfig.c
CommitLineData
12618416 1/** @file\r
55a64ae0 2 Helper functions for configuring or getting the parameters relating to iSCSI.\r
6a690e23 3\r
ace28761 4Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
7a444476 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
6a690e23 12\r
12618416 13**/\r
6a690e23 14\r
15#include "IScsiImpl.h"\r
16\r
7e3bcccb 17CHAR16 mVendorStorageName[] = L"ISCSI_CONFIG_IFR_NVDATA";\r
f2a94e25 18BOOLEAN mIScsiDeviceListUpdated = FALSE;\r
19UINTN mNumberOfIScsiDevices = 0;\r
20ISCSI_FORM_CALLBACK_INFO *mCallbackInfo = NULL;\r
6a690e23 21\r
e48e37fc 22LIST_ENTRY mIScsiConfigFormList = {\r
6a690e23 23 &mIScsiConfigFormList,\r
24 &mIScsiConfigFormList\r
25};\r
26\r
f6f910dd 27HII_VENDOR_DEVICE_PATH mIScsiHiiVendorDevicePath = {\r
28 {\r
29 {\r
30 HARDWARE_DEVICE_PATH,\r
31 HW_VENDOR_DP,\r
32 {\r
33 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),\r
34 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)\r
35 }\r
36 },\r
c8ad2d7a 37 IP4_ISCSI_CONFIG_GUID\r
f6f910dd 38 },\r
39 {\r
40 END_DEVICE_PATH_TYPE,\r
41 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
42 { \r
43 (UINT8) (END_DEVICE_PATH_LENGTH),\r
44 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)\r
45 }\r
46 }\r
47};\r
48\r
12618416 49/**\r
50 Convert the IPv4 address into a dotted string.\r
51\r
669314e5 52 @param[in] Ip The IPv4 address.\r
53 @param[out] Str The dotted IP string.\r
12618416 54**/\r
6a690e23 55VOID\r
56IScsiIpToStr (\r
57 IN EFI_IPv4_ADDRESS *Ip,\r
58 OUT CHAR16 *Str\r
59 )\r
6a690e23 60{\r
61 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
62}\r
63\r
312e3bdf 64\r
65/**\r
66 Parse IsId in string format and convert it to binary.\r
67\r
68 @param[in] String The buffer of the string to be parsed.\r
69 @param[in, out] IsId The buffer to store IsId.\r
70\r
71 @retval EFI_SUCCESS The operation finished successfully.\r
72 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
73\r
74**/\r
75EFI_STATUS\r
76IScsiParseIsIdFromString (\r
77 IN CONST CHAR16 *String,\r
78 IN OUT UINT8 *IsId\r
79 )\r
80{\r
81 UINT8 Index;\r
82 CHAR16 *IsIdStr;\r
83 CHAR16 TempStr[3];\r
84 UINTN NodeVal;\r
85 CHAR16 PortString[ISCSI_NAME_IFR_MAX_SIZE];\r
86 EFI_INPUT_KEY Key;\r
87\r
88 if ((String == NULL) || (IsId == NULL)) {\r
89 return EFI_INVALID_PARAMETER;\r
90 }\r
91\r
92 IsIdStr = (CHAR16 *) String;\r
93\r
94 if (StrLen (IsIdStr) != 6) {\r
95 UnicodeSPrint (\r
96 PortString,\r
dbcecd5d 97 (UINTN) sizeof (PortString),\r
312e3bdf 98 L"Error! Input is incorrect, please input 6 hex numbers!\n"\r
99 );\r
100\r
101 CreatePopUp (\r
102 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
103 &Key,\r
104 PortString,\r
105 NULL\r
106 );\r
107\r
108 return EFI_INVALID_PARAMETER;\r
109 }\r
110\r
111 for (Index = 3; Index < 6; Index++) {\r
112 CopyMem (TempStr, IsIdStr, sizeof (TempStr));\r
113 TempStr[2] = L'\0';\r
114\r
115 //\r
116 // Convert the string to IsId. StrHexToUintn stops at the first character\r
117 // that is not a valid hex character, '\0' here.\r
118 //\r
119 NodeVal = StrHexToUintn (TempStr);\r
120\r
121 IsId[Index] = (UINT8) NodeVal;\r
122\r
123 IsIdStr = IsIdStr + 2;\r
124 }\r
125\r
126 return EFI_SUCCESS;\r
127}\r
128\r
129/**\r
130 Convert IsId from binary to string format.\r
131\r
132 @param[out] String The buffer to store the converted string.\r
133 @param[in] IsId The buffer to store IsId.\r
134\r
135 @retval EFI_SUCCESS The string converted successfully.\r
136 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
137\r
138**/\r
139EFI_STATUS\r
140IScsiConvertIsIdToString (\r
141 OUT CHAR16 *String,\r
142 IN UINT8 *IsId\r
143 )\r
144{\r
145 UINT8 Index;\r
146 UINTN Number;\r
147\r
148 if ((String == NULL) || (IsId == NULL)) {\r
149 return EFI_INVALID_PARAMETER;\r
150 }\r
151\r
152 for (Index = 0; Index < 6; Index++) {\r
153 if (IsId[Index] <= 0xF) {\r
154 Number = UnicodeSPrint (\r
155 String,\r
156 2 * ISID_CONFIGURABLE_STORAGE,\r
157 L"0%X",\r
158 (UINTN) IsId[Index]\r
159 );\r
160 } else {\r
161 Number = UnicodeSPrint (\r
162 String,\r
163 2 * ISID_CONFIGURABLE_STORAGE,\r
164 L"%X",\r
165 (UINTN) IsId[Index]\r
166 );\r
167\r
168 }\r
169\r
170 String = String + Number;\r
171 }\r
172\r
173 *String = L'\0';\r
174\r
175 return EFI_SUCCESS;\r
176}\r
177\r
178\r
12618416 179/**\r
6a690e23 180 Update the list of iSCSI devices the iSCSI driver is controlling.\r
779ae357 181\r
669314e5 182 @retval EFI_SUCCESS The callback successfully handled the action.\r
963dbb30 183 @retval Others Other errors as indicated. \r
12618416 184**/\r
185EFI_STATUS\r
186IScsiUpdateDeviceList (\r
187 VOID\r
188 )\r
6a690e23 189{\r
190 EFI_STATUS Status;\r
191 ISCSI_DEVICE_LIST *DeviceList;\r
192 UINTN DataSize;\r
193 UINTN NumHandles;\r
194 EFI_HANDLE *Handles;\r
195 UINTN HandleIndex;\r
196 UINTN Index;\r
197 UINTN LastDeviceIndex;\r
779ae357 198 EFI_MAC_ADDRESS MacAddress;\r
199 UINTN HwAddressSize;\r
200 UINT16 VlanId;\r
6a690e23 201 ISCSI_MAC_INFO *CurMacInfo;\r
202 ISCSI_MAC_INFO TempMacInfo;\r
779ae357 203 CHAR16 MacString[70];\r
6a690e23 204 UINTN DeviceListSize;\r
205\r
206 //\r
779ae357 207 // Dump all the handles the Managed Network Service Binding Protocol is installed on.\r
6a690e23 208 //\r
209 Status = gBS->LocateHandleBuffer (\r
210 ByProtocol,\r
779ae357 211 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
6a690e23 212 NULL,\r
213 &NumHandles,\r
214 &Handles\r
215 );\r
216 if (EFI_ERROR (Status)) {\r
217 return Status;\r
218 }\r
219\r
220 DataSize = 0;\r
221 Status = gRT->GetVariable (\r
222 L"iSCSIDeviceList",\r
c8ad2d7a 223 &gIp4IScsiConfigGuid,\r
6a690e23 224 NULL,\r
225 &DataSize,\r
226 NULL\r
227 );\r
228 if (Status == EFI_BUFFER_TOO_SMALL) {\r
e48e37fc 229 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DataSize);\r
523f48e7 230 ASSERT (DeviceList != NULL);\r
6a690e23 231\r
232 gRT->GetVariable (\r
233 L"iSCSIDeviceList",\r
c8ad2d7a 234 &gIp4IScsiConfigGuid,\r
6a690e23 235 NULL,\r
236 &DataSize,\r
237 DeviceList\r
238 );\r
239\r
240 LastDeviceIndex = 0;\r
241\r
242 for (HandleIndex = 0; HandleIndex < NumHandles; HandleIndex++) {\r
779ae357 243 Status = NetLibGetMacAddress (Handles[HandleIndex], &MacAddress, &HwAddressSize);\r
244 ASSERT (Status == EFI_SUCCESS);\r
245 VlanId = NetLibGetVlanId (Handles[HandleIndex]);\r
6a690e23 246\r
247 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
248 CurMacInfo = &DeviceList->MacInfo[Index];\r
779ae357 249 if ((CurMacInfo->Len == HwAddressSize) &&\r
250 (CurMacInfo->VlanId == VlanId) &&\r
251 (NET_MAC_EQUAL (&CurMacInfo->Mac, MacAddress.Addr, HwAddressSize))\r
6a690e23 252 ) {\r
253 //\r
254 // The previous configured NIC is still here.\r
255 //\r
256 if (Index != LastDeviceIndex) {\r
257 //\r
258 // Swap the current MAC address entry with the one indexed by\r
259 // LastDeviceIndex.\r
260 //\r
e48e37fc 261 CopyMem (&TempMacInfo, CurMacInfo, sizeof (ISCSI_MAC_INFO));\r
262 CopyMem (CurMacInfo, &DeviceList->MacInfo[LastDeviceIndex], sizeof (ISCSI_MAC_INFO));\r
263 CopyMem (&DeviceList->MacInfo[LastDeviceIndex], &TempMacInfo, sizeof (ISCSI_MAC_INFO));\r
6a690e23 264 }\r
265\r
266 LastDeviceIndex++;\r
267 }\r
268 }\r
269\r
270 if (LastDeviceIndex == DeviceList->NumDevice) {\r
271 break;\r
272 }\r
273 }\r
274\r
275 for (Index = LastDeviceIndex; Index < DeviceList->NumDevice; Index++) {\r
276 //\r
277 // delete the variables\r
278 //\r
279 CurMacInfo = &DeviceList->MacInfo[Index];\r
779ae357 280 IScsiMacAddrToStr (&CurMacInfo->Mac, CurMacInfo->Len, CurMacInfo->VlanId, MacString);\r
6a690e23 281 gRT->SetVariable (MacString, &gEfiIScsiInitiatorNameProtocolGuid, 0, 0, NULL);\r
c8ad2d7a 282 gRT->SetVariable (MacString, &gIScsiCHAPAuthInfoGuid, 0, 0, NULL);\r
6a690e23 283 }\r
284\r
766c7483 285 FreePool (DeviceList);\r
6a690e23 286 } else if (Status != EFI_NOT_FOUND) {\r
766c7483 287 FreePool (Handles);\r
6a690e23 288 return Status;\r
289 }\r
290 //\r
291 // Construct the new iSCSI device list.\r
292 //\r
293 DeviceListSize = sizeof (ISCSI_DEVICE_LIST) + (NumHandles - 1) * sizeof (ISCSI_MAC_INFO);\r
e48e37fc 294 DeviceList = (ISCSI_DEVICE_LIST *) AllocatePool (DeviceListSize);\r
523f48e7 295 ASSERT (DeviceList != NULL);\r
6a690e23 296 DeviceList->NumDevice = (UINT8) NumHandles;\r
297\r
298 for (Index = 0; Index < NumHandles; Index++) {\r
779ae357 299 NetLibGetMacAddress (Handles[Index], &MacAddress, &HwAddressSize);\r
6a690e23 300\r
301 CurMacInfo = &DeviceList->MacInfo[Index];\r
779ae357 302 CopyMem (&CurMacInfo->Mac, MacAddress.Addr, HwAddressSize);\r
303 CurMacInfo->Len = (UINT8) HwAddressSize;\r
304 CurMacInfo->VlanId = NetLibGetVlanId (Handles[Index]);\r
6a690e23 305 }\r
306\r
307 gRT->SetVariable (\r
308 L"iSCSIDeviceList",\r
c8ad2d7a 309 &gIp4IScsiConfigGuid,\r
6a690e23 310 ISCSI_CONFIG_VAR_ATTR,\r
311 DeviceListSize,\r
312 DeviceList\r
313 );\r
314\r
766c7483 315 FreePool (DeviceList);\r
316 FreePool (Handles);\r
6a690e23 317\r
318 return Status;\r
319}\r
320\r
12618416 321/**\r
322 Get the iSCSI configuration form entry by the index of the goto opcode actived.\r
323\r
669314e5 324 @param[in] Index The 0-based index of the goto opcode actived.\r
12618416 325\r
669314e5 326 @return The iSCSI configuration form entry found.\r
12618416 327**/\r
6a690e23 328ISCSI_CONFIG_FORM_ENTRY *\r
329IScsiGetConfigFormEntryByIndex (\r
330 IN UINT32 Index\r
331 )\r
6a690e23 332{\r
333 UINT32 CurrentIndex;\r
e48e37fc 334 LIST_ENTRY *Entry;\r
6a690e23 335 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
336\r
337 CurrentIndex = 0;\r
338 ConfigFormEntry = NULL;\r
339\r
340 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
341 if (CurrentIndex == Index) {\r
342 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
343 break;\r
344 }\r
345\r
346 CurrentIndex++;\r
347 }\r
348\r
349 return ConfigFormEntry;\r
350}\r
351\r
12618416 352/**\r
353 Convert the iSCSI configuration data into the IFR data.\r
354\r
c5de0d55 355 @param[in] ConfigFormEntry The iSCSI configuration form entry.\r
356 @param[out] IfrNvData The IFR nv data.\r
312e3bdf 357\r
12618416 358**/\r
6a690e23 359VOID\r
360IScsiConvertDeviceConfigDataToIfrNvData (\r
c5de0d55 361 IN ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry,\r
362 OUT ISCSI_CONFIG_IFR_NVDATA *IfrNvData\r
6a690e23 363 )\r
6a690e23 364{\r
365 ISCSI_SESSION_CONFIG_NVDATA *SessionConfigData;\r
366 ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfigData;\r
367\r
368 //\r
369 // Normal session configuration parameters.\r
370 //\r
371 SessionConfigData = &ConfigFormEntry->SessionConfigData;\r
372 IfrNvData->Enabled = SessionConfigData->Enabled;\r
373\r
374 IfrNvData->InitiatorInfoFromDhcp = SessionConfigData->InitiatorInfoFromDhcp;\r
375 IfrNvData->TargetInfoFromDhcp = SessionConfigData->TargetInfoFromDhcp;\r
376 IfrNvData->TargetPort = SessionConfigData->TargetPort;\r
377\r
378 IScsiIpToStr (&SessionConfigData->LocalIp, IfrNvData->LocalIp);\r
379 IScsiIpToStr (&SessionConfigData->SubnetMask, IfrNvData->SubnetMask);\r
380 IScsiIpToStr (&SessionConfigData->Gateway, IfrNvData->Gateway);\r
381 IScsiIpToStr (&SessionConfigData->TargetIp, IfrNvData->TargetIp);\r
382\r
383 IScsiAsciiStrToUnicodeStr (SessionConfigData->TargetName, IfrNvData->TargetName);\r
384\r
385 IScsiLunToUnicodeStr (SessionConfigData->BootLun, IfrNvData->BootLun);\r
386\r
312e3bdf 387 IScsiConvertIsIdToString (IfrNvData->IsId, SessionConfigData->IsId);\r
388\r
6a690e23 389 //\r
390 // CHAP authentication parameters.\r
391 //\r
392 AuthConfigData = &ConfigFormEntry->AuthConfigData;\r
393\r
394 IfrNvData->CHAPType = AuthConfigData->CHAPType;\r
395\r
396 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPName, IfrNvData->CHAPName);\r
397 IScsiAsciiStrToUnicodeStr (AuthConfigData->CHAPSecret, IfrNvData->CHAPSecret);\r
398 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPName, IfrNvData->ReverseCHAPName);\r
399 IScsiAsciiStrToUnicodeStr (AuthConfigData->ReverseCHAPSecret, IfrNvData->ReverseCHAPSecret);\r
400}\r
401\r
12618416 402/**\r
669314e5 403 This function allows the caller to request the current\r
404 configuration for one or more named elements. The resulting\r
405 string is in <ConfigAltResp> format. Any and all alternative\r
406 configuration strings shall also be appended to the end of the\r
407 current configuration string. If they are, they must appear\r
408 after the current configuration. They must contain the same\r
409 routing (GUID, NAME, PATH) as the current configuration string.\r
410 They must have an additional description indicating the type of\r
411 alternative configuration the string represents,\r
412 "ALTCFG=<StringToken>". That <StringToken> (when\r
413 converted from Hex UNICODE to binary) is a reference to a\r
414 string in the associated string pack.\r
415\r
416 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
417 @param[in] Request A null-terminated Unicode string in\r
418 <ConfigRequest> format. Note that this\r
419 includes the routing information as well as\r
420 the configurable name / value pairs. It is\r
421 invalid for this string to be in\r
422 <MultiConfigRequest> format.\r
423 @param[out] Progress On return, points to a character in the\r
424 Request string. Points to the string's null\r
425 terminator if request was successful. Points\r
426 to the most recent "&" before the first\r
427 failing name / value pair (or the beginning\r
428 of the string if the failure is in the first\r
429 name / value pair) if the request was not\r
430 successful.\r
431 @param[out] Results A null-terminated Unicode string in\r
432 <ConfigAltResp> format which has all values\r
433 filled in for the names in the Request string.\r
434 String to be allocated by the called function.\r
435\r
436 @retval EFI_SUCCESS The Results string is filled with the\r
437 values corresponding to all requested\r
438 names.\r
439 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
440 parts of the results that must be\r
441 stored awaiting possible future\r
442 protocols.\r
443 @retval EFI_INVALID_PARAMETER For example, passing in a NULL\r
444 for the Request parameter\r
445 would result in this type of\r
446 error. In this case, the\r
447 Progress parameter would be\r
448 set to NULL. \r
449 @retval EFI_NOT_FOUND Routing data doesn't match any\r
450 known driver. Progress set to the\r
451 first character in the routing header.\r
452 Note: There is no requirement that the\r
453 driver validate the routing data. It\r
454 must skip the <ConfigHdr> in order to\r
455 process the names.\r
456 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set\r
457 to most recent & before the\r
458 error or the beginning of the\r
459 string.\r
460 @retval EFI_INVALID_PARAMETER Unknown name. Progress points\r
461 to the & before the name in\r
462 question.Currently not implemented.\r
12618416 463**/\r
6a690e23 464EFI_STATUS\r
465EFIAPI\r
93e3992d 466IScsiFormExtractConfig (\r
467 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
468 IN CONST EFI_STRING Request,\r
469 OUT EFI_STRING *Progress,\r
470 OUT EFI_STRING *Results\r
6a690e23 471 )\r
6a690e23 472{\r
93e3992d 473 EFI_STATUS Status;\r
4da9ccc9 474 CHAR8 InitiatorName[ISCSI_NAME_MAX_SIZE];\r
93e3992d 475 UINTN BufferSize;\r
476 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
477 ISCSI_FORM_CALLBACK_INFO *Private;\r
478 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
59aefb7e
LG
479 EFI_STRING ConfigRequestHdr;\r
480 EFI_STRING ConfigRequest;\r
481 BOOLEAN AllocatedRequest;\r
482 UINTN Size;\r
6a690e23 483\r
59aefb7e 484 if (Progress == NULL || Results == NULL) {\r
669314e5 485 return EFI_INVALID_PARAMETER;\r
8d00a0f1 486 }\r
59aefb7e 487\r
ae79d2f9 488 *Progress = Request;\r
c8ad2d7a 489 if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gIp4IScsiConfigGuid, mVendorStorageName)) {\r
59aefb7e
LG
490 return EFI_NOT_FOUND;\r
491 }\r
492\r
493 ConfigRequestHdr = NULL;\r
494 ConfigRequest = NULL;\r
495 AllocatedRequest = FALSE;\r
496 Size = 0;\r
8d00a0f1 497\r
6a690e23 498 if (!mIScsiDeviceListUpdated) {\r
499 //\r
500 // Update the device list.\r
501 //\r
502 IScsiUpdateDeviceList ();\r
503 mIScsiDeviceListUpdated = TRUE;\r
504 }\r
505\r
93e3992d 506 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
507 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
508 ASSERT (IfrNvData != NULL);\r
509 if (Private->Current != NULL) {\r
510 IScsiConvertDeviceConfigDataToIfrNvData (Private->Current, IfrNvData);\r
511 }\r
6a690e23 512\r
4da9ccc9 513 BufferSize = ISCSI_NAME_MAX_SIZE;\r
6a690e23 514 Status = gIScsiInitiatorName.Get (&gIScsiInitiatorName, &BufferSize, InitiatorName);\r
515 if (EFI_ERROR (Status)) {\r
516 IfrNvData->InitiatorName[0] = L'\0';\r
517 } else {\r
518 IScsiAsciiStrToUnicodeStr (InitiatorName, IfrNvData->InitiatorName);\r
519 }\r
520\r
93e3992d 521 //\r
522 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
523 //\r
524 HiiConfigRouting = Private->ConfigRouting;\r
525 BufferSize = sizeof (ISCSI_CONFIG_IFR_NVDATA);\r
59aefb7e
LG
526 ConfigRequest = Request;\r
527 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
528 //\r
529 // Request has no request element, construct full request string.\r
530 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
531 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
532 //\r
c8ad2d7a 533 ConfigRequestHdr = HiiConstructConfigHdr (&gIp4IScsiConfigGuid, mVendorStorageName, Private->DriverHandle);\r
59aefb7e
LG
534 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
535 ConfigRequest = AllocateZeroPool (Size);\r
536 ASSERT (ConfigRequest != NULL);\r
537 AllocatedRequest = TRUE;\r
538 UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
539 FreePool (ConfigRequestHdr);\r
540 }\r
93e3992d 541 Status = HiiConfigRouting->BlockToConfig (\r
542 HiiConfigRouting,\r
59aefb7e 543 ConfigRequest,\r
93e3992d 544 (UINT8 *) IfrNvData,\r
545 BufferSize,\r
546 Results,\r
547 Progress\r
548 );\r
766c7483 549 FreePool (IfrNvData);\r
59aefb7e
LG
550 //\r
551 // Free the allocated config request string.\r
552 //\r
553 if (AllocatedRequest) {\r
554 FreePool (ConfigRequest);\r
555 ConfigRequest = NULL;\r
556 }\r
557\r
558 //\r
559 // Set Progress string to the original request string.\r
560 //\r
561 if (Request == NULL) {\r
562 *Progress = NULL;\r
563 } else if (StrStr (Request, L"OFFSET") == NULL) {\r
564 *Progress = Request + StrLen (Request);\r
565 }\r
566\r
93e3992d 567 return Status;\r
6a690e23 568}\r
569\r
12618416 570/**\r
669314e5 571 This function applies changes in a driver's configuration.\r
572 Input is a Configuration, which has the routing data for this\r
573 driver followed by name / value configuration pairs. The driver\r
574 must apply those pairs to its configurable storage. If the\r
575 driver's configuration is stored in a linear block of data\r
55a64ae0 576 and the driver's name / value pairs are in <BlockConfig>\r
669314e5 577 format, it may use the ConfigToBlock helper function (above) to\r
578 simplify the job. Currently not implemented.\r
579\r
580 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
581 @param[in] Configuration A null-terminated Unicode string in\r
582 <ConfigString> format. \r
583 @param[out] Progress A pointer to a string filled in with the\r
584 offset of the most recent '&' before the\r
585 first failing name / value pair (or the\r
586 beginn ing of the string if the failure\r
587 is in the first name / value pair) or\r
588 the terminating NULL if all was\r
589 successful.\r
590\r
591 @retval EFI_SUCCESS The results have been distributed or are\r
592 awaiting distribution. \r
e1f1fb16 593 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the\r
669314e5 594 parts of the results that must be\r
595 stored awaiting possible future\r
596 protocols.\r
597 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the\r
598 Results parameter would result\r
599 in this type of error.\r
600 @retval EFI_NOT_FOUND Target for the specified routing data\r
601 was not found.\r
12618416 602**/\r
6a690e23 603EFI_STATUS\r
604EFIAPI\r
93e3992d 605IScsiFormRouteConfig (\r
606 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
607 IN CONST EFI_STRING Configuration,\r
608 OUT EFI_STRING *Progress\r
6a690e23 609 )\r
12618416 610{\r
ae79d2f9
LG
611 if (Configuration == NULL || Progress == NULL) {\r
612 return EFI_INVALID_PARAMETER;\r
613 }\r
614\r
615 //\r
616 // Check routing data in <ConfigHdr>.\r
617 // Note: if only one Storage is used, then this checking could be skipped.\r
618 //\r
c8ad2d7a 619 if (!HiiIsConfigHdrMatch (Configuration, &gIp4IScsiConfigGuid, mVendorStorageName)) {\r
ae79d2f9
LG
620 *Progress = Configuration;\r
621 return EFI_NOT_FOUND;\r
622 }\r
623\r
624 *Progress = Configuration + StrLen (Configuration);\r
12618416 625 return EFI_SUCCESS;\r
626}\r
6a690e23 627\r
12618416 628/**\r
669314e5 629 This function is called to provide results data to the driver.\r
630 This data consists of a unique key that is used to identify\r
631 which data is either being passed back or being asked for.\r
632\r
633 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
634 @param[in] Action Specifies the type of action taken by the browser.\r
635 @param[in] QuestionId A unique value which is sent to the original\r
636 exporting driver so that it can identify the type\r
637 of data to expect. The format of the data tends to \r
638 vary based on the opcode that enerated the callback.\r
639 @param[in] Type The type of value for the question.\r
640 @param[in] Value A pointer to the data being sent to the original\r
641 exporting driver.\r
642 @param[out] ActionRequest On return, points to the action requested by the\r
643 callback function.\r
644\r
645 @retval EFI_SUCCESS The callback successfully handled the action.\r
646 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the\r
647 variable and its data.\r
648 @retval EFI_DEVICE_ERROR The variable could not be saved.\r
649 @retval EFI_UNSUPPORTED The specified Action is not supported by the\r
650 callback.Currently not implemented.\r
651 @retval EFI_INVALID_PARAMETERS Passing in wrong parameter. \r
963dbb30 652 @retval Others Other errors as indicated. \r
12618416 653**/\r
93e3992d 654EFI_STATUS\r
655EFIAPI\r
656IScsiFormCallback (\r
657 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
f3e1569d 658 IN EFI_BROWSER_ACTION Action,\r
669314e5 659 IN EFI_QUESTION_ID QuestionId,\r
93e3992d 660 IN UINT8 Type,\r
661 IN EFI_IFR_TYPE_VALUE *Value,\r
662 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
663 )\r
6a690e23 664{\r
665 ISCSI_FORM_CALLBACK_INFO *Private;\r
666 UINTN BufferSize;\r
4da9ccc9 667 CHAR8 IScsiName[ISCSI_NAME_MAX_SIZE];\r
6a690e23 668 CHAR16 PortString[128];\r
669 CHAR8 Ip4String[IP4_STR_MAX_SIZE];\r
670 CHAR8 LunString[ISCSI_LUN_STR_MAX_LEN];\r
671 UINT64 Lun;\r
6c7a807a 672 EFI_STRING_ID DeviceFormTitleToken;\r
6a690e23 673 ISCSI_CONFIG_IFR_NVDATA *IfrNvData;\r
674 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
675 EFI_IP_ADDRESS HostIp;\r
676 EFI_IP_ADDRESS SubnetMask;\r
677 EFI_IP_ADDRESS Gateway;\r
678 EFI_STATUS Status;\r
63d55bb9 679 EFI_INPUT_KEY Key;\r
6a690e23 680\r
3a4e7a3e
ED
681 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {\r
682 return EFI_UNSUPPORTED;\r
683 }\r
684\r
685 Private = ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK (This);\r
686 //\r
687 // Retrive uncommitted data from Browser\r
688 //\r
689 IfrNvData = AllocateZeroPool (sizeof (ISCSI_CONFIG_IFR_NVDATA));\r
690 ASSERT (IfrNvData != NULL);\r
691 if (!HiiGetBrowserData (&gIp4IScsiConfigGuid, mVendorStorageName, sizeof (ISCSI_CONFIG_IFR_NVDATA), (UINT8 *) IfrNvData)) {\r
692 FreePool (IfrNvData);\r
693 return EFI_NOT_FOUND;\r
694 }\r
695 Status = EFI_SUCCESS;\r
696\r
083f7c69 697 if (Action == EFI_BROWSER_ACTION_CHANGING) {\r
3a4e7a3e
ED
698 if ((QuestionId >= KEY_DEVICE_ENTRY_BASE) && (QuestionId < (mNumberOfIScsiDevices + KEY_DEVICE_ENTRY_BASE))) {\r
699 //\r
700 // In case goto the device configuration form, update the device form title.\r
701 //\r
702 ConfigFormEntry = IScsiGetConfigFormEntryByIndex ((UINT32) (QuestionId - KEY_DEVICE_ENTRY_BASE));\r
703 ASSERT (ConfigFormEntry != NULL);\r
6a690e23 704\r
dbcecd5d 705 UnicodeSPrint (PortString, (UINTN) sizeof (PortString), L"Port %s", ConfigFormEntry->MacString);\r
3a4e7a3e
ED
706 DeviceFormTitleToken = (EFI_STRING_ID) STR_ISCSI_DEVICE_FORM_TITLE;\r
707 HiiSetString (Private->RegisteredHandle, DeviceFormTitleToken, PortString, NULL);\r
708\r
709 IScsiConvertDeviceConfigDataToIfrNvData (ConfigFormEntry, IfrNvData);\r
710\r
711 Private->Current = ConfigFormEntry;\r
712 }\r
713 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
714 switch (QuestionId) { \r
083f7c69
ED
715 case KEY_INITIATOR_NAME:\r
716 IScsiUnicodeStrToAsciiStr (IfrNvData->InitiatorName, IScsiName);\r
717 BufferSize = AsciiStrSize (IScsiName);\r
6a690e23 718\r
083f7c69
ED
719 Status = gIScsiInitiatorName.Set (&gIScsiInitiatorName, &BufferSize, IScsiName);\r
720 if (EFI_ERROR (Status)) {\r
721 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid iSCSI Name!", NULL);\r
722 }\r
6a690e23 723\r
eda08e59 724 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
083f7c69 725 break;\r
6a690e23 726\r
083f7c69
ED
727 case KEY_LOCAL_IP:\r
728 IScsiUnicodeStrToAsciiStr (IfrNvData->LocalIp, Ip4String);\r
729 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
730 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
731 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
732 Status = EFI_INVALID_PARAMETER;\r
733 } else {\r
734 CopyMem (&Private->Current->SessionConfigData.LocalIp, &HostIp.v4, sizeof (HostIp.v4));\r
735 }\r
6a690e23 736\r
083f7c69 737 break;\r
6a690e23 738\r
083f7c69
ED
739 case KEY_SUBNET_MASK:\r
740 IScsiUnicodeStrToAsciiStr (IfrNvData->SubnetMask, Ip4String);\r
741 Status = IScsiAsciiStrToIp (Ip4String, &SubnetMask.v4);\r
742 if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (IScsiGetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
743 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
744 Status = EFI_INVALID_PARAMETER;\r
745 } else {\r
746 CopyMem (&Private->Current->SessionConfigData.SubnetMask, &SubnetMask.v4, sizeof (SubnetMask.v4));\r
747 }\r
6a690e23 748\r
083f7c69 749 break;\r
6a690e23 750\r
083f7c69
ED
751 case KEY_GATE_WAY:\r
752 IScsiUnicodeStrToAsciiStr (IfrNvData->Gateway, Ip4String);\r
753 Status = IScsiAsciiStrToIp (Ip4String, &Gateway.v4);\r
754 if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
755 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
756 Status = EFI_INVALID_PARAMETER;\r
757 } else {\r
758 CopyMem (&Private->Current->SessionConfigData.Gateway, &Gateway.v4, sizeof (Gateway.v4));\r
759 }\r
6a690e23 760\r
083f7c69 761 break;\r
6a690e23 762\r
083f7c69
ED
763 case KEY_TARGET_IP:\r
764 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetIp, Ip4String);\r
765 Status = IScsiAsciiStrToIp (Ip4String, &HostIp.v4);\r
766 if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
767 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
768 Status = EFI_INVALID_PARAMETER;\r
769 } else {\r
770 CopyMem (&Private->Current->SessionConfigData.TargetIp, &HostIp.v4, sizeof (HostIp.v4));\r
771 }\r
6a690e23 772\r
083f7c69 773 break;\r
6a690e23 774\r
083f7c69
ED
775 case KEY_TARGET_NAME:\r
776 IScsiUnicodeStrToAsciiStr (IfrNvData->TargetName, IScsiName);\r
777 Status = IScsiNormalizeName (IScsiName, AsciiStrLen (IScsiName));\r
778 if (EFI_ERROR (Status)) {\r
779 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid iSCSI Name!", NULL);\r
780 } else {\r
781 AsciiStrCpy (Private->Current->SessionConfigData.TargetName, IScsiName);\r
782 }\r
6a690e23 783\r
083f7c69 784 break;\r
6a690e23 785\r
083f7c69
ED
786 case KEY_DHCP_ENABLE:\r
787 if (IfrNvData->InitiatorInfoFromDhcp == 0) {\r
788 IfrNvData->TargetInfoFromDhcp = 0;\r
789 }\r
6a690e23 790\r
083f7c69 791 break;\r
6a690e23 792\r
083f7c69
ED
793 case KEY_BOOT_LUN:\r
794 IScsiUnicodeStrToAsciiStr (IfrNvData->BootLun, LunString);\r
795 Status = IScsiAsciiStrToLun (LunString, (UINT8 *) &Lun);\r
796 if (EFI_ERROR (Status)) {\r
797 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid LUN string!", NULL);\r
798 } else {\r
799 CopyMem (Private->Current->SessionConfigData.BootLun, &Lun, sizeof (Lun));\r
800 }\r
6a690e23 801\r
083f7c69 802 break;\r
6a690e23 803\r
083f7c69
ED
804 case KEY_CHAP_NAME:\r
805 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPName, Private->Current->AuthConfigData.CHAPName);\r
806 break;\r
6a690e23 807\r
083f7c69
ED
808 case KEY_CHAP_SECRET:\r
809 IScsiUnicodeStrToAsciiStr (IfrNvData->CHAPSecret, Private->Current->AuthConfigData.CHAPSecret);\r
810 break;\r
6a690e23 811\r
083f7c69
ED
812 case KEY_REVERSE_CHAP_NAME:\r
813 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPName, Private->Current->AuthConfigData.ReverseCHAPName);\r
814 break;\r
6a690e23 815\r
083f7c69
ED
816 case KEY_REVERSE_CHAP_SECRET:\r
817 IScsiUnicodeStrToAsciiStr (IfrNvData->ReverseCHAPSecret, Private->Current->AuthConfigData.ReverseCHAPSecret);\r
818 break;\r
6a690e23 819\r
083f7c69
ED
820 case KEY_CONFIG_ISID:\r
821 IScsiParseIsIdFromString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
822 IScsiConvertIsIdToString (IfrNvData->IsId, Private->Current->SessionConfigData.IsId);\r
312e3bdf 823\r
083f7c69 824 break;\r
312e3bdf 825\r
083f7c69
ED
826 case KEY_SAVE_CHANGES:\r
827 //\r
828 // First, update those fields which don't have INTERACTIVE set.\r
829 //\r
830 Private->Current->SessionConfigData.Enabled = IfrNvData->Enabled;\r
831 Private->Current->SessionConfigData.InitiatorInfoFromDhcp = IfrNvData->InitiatorInfoFromDhcp;\r
832 Private->Current->SessionConfigData.TargetPort = IfrNvData->TargetPort;\r
833 if (Private->Current->SessionConfigData.TargetPort == 0) {\r
834 Private->Current->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;\r
835 }\r
6a690e23 836\r
083f7c69
ED
837 Private->Current->SessionConfigData.TargetInfoFromDhcp = IfrNvData->TargetInfoFromDhcp;\r
838 Private->Current->AuthConfigData.CHAPType = IfrNvData->CHAPType;\r
6a690e23 839\r
6a690e23 840 //\r
083f7c69 841 // Only do full parameter validation if iSCSI is enabled on this device.\r
6a690e23 842 //\r
083f7c69
ED
843 if (Private->Current->SessionConfigData.Enabled) {\r
844 //\r
845 // Validate the address configuration of the Initiator if DHCP isn't\r
846 // deployed.\r
847 //\r
848 if (!Private->Current->SessionConfigData.InitiatorInfoFromDhcp) {\r
849 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.LocalIp, sizeof (HostIp.v4));\r
850 CopyMem (&SubnetMask.v4, &Private->Current->SessionConfigData.SubnetMask, sizeof (SubnetMask.v4));\r
851 CopyMem (&Gateway.v4, &Private->Current->SessionConfigData.Gateway, sizeof (Gateway.v4));\r
852\r
853 if ((Gateway.Addr[0] != 0)) {\r
854 if (SubnetMask.Addr[0] == 0) {\r
855 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Gateway address is set but subnet mask is zero.", NULL);\r
856 Status = EFI_INVALID_PARAMETER;\r
857 break;\r
858 } else if (!IP4_NET_EQUAL (HostIp.Addr[0], Gateway.Addr[0], SubnetMask.Addr[0])) {\r
859 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Local IP and Gateway are not in the same subnet.", NULL);\r
860 Status = EFI_INVALID_PARAMETER;\r
861 break;\r
862 }\r
863 }\r
864 }\r
865 //\r
866 // Validate target configuration if DHCP isn't deployed.\r
867 //\r
868 if (!Private->Current->SessionConfigData.TargetInfoFromDhcp) {\r
869 CopyMem (&HostIp.v4, &Private->Current->SessionConfigData.TargetIp, sizeof (HostIp.v4));\r
870 if (!NetIp4IsUnicast (NTOHL (HostIp.Addr[0]), 0)) {\r
871 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Target IP is invalid!", NULL);\r
6a690e23 872 Status = EFI_INVALID_PARAMETER;\r
873 break;\r
874 }\r
875 }\r
6a690e23 876\r
083f7c69
ED
877 if (IfrNvData->CHAPType != ISCSI_CHAP_NONE) {\r
878 if ((IfrNvData->CHAPName[0] == '\0') || (IfrNvData->CHAPSecret[0] == '\0')) {\r
879 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"CHAP Name or CHAP Secret is invalid!", NULL);\r
880 Status = EFI_INVALID_PARAMETER;\r
881 break;\r
882 }\r
6a690e23 883\r
083f7c69
ED
884 if ((IfrNvData->CHAPType == ISCSI_CHAP_MUTUAL) &&\r
885 ((IfrNvData->ReverseCHAPName[0] == '\0') || (IfrNvData->ReverseCHAPSecret[0] == '\0'))\r
886 ) {\r
887 CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Reverse CHAP Name or Reverse CHAP Secret is invalid!", NULL);\r
888 Status = EFI_INVALID_PARAMETER;\r
889 break;\r
890 }\r
6a690e23 891 }\r
892 }\r
6a690e23 893\r
083f7c69
ED
894 BufferSize = sizeof (Private->Current->SessionConfigData);\r
895 gRT->SetVariable (\r
896 Private->Current->MacString,\r
897 &gEfiIScsiInitiatorNameProtocolGuid,\r
898 ISCSI_CONFIG_VAR_ATTR,\r
899 BufferSize,\r
900 &Private->Current->SessionConfigData\r
901 );\r
902\r
903 BufferSize = sizeof (Private->Current->AuthConfigData);\r
904 gRT->SetVariable (\r
905 Private->Current->MacString,\r
c8ad2d7a 906 &gIScsiCHAPAuthInfoGuid,\r
083f7c69
ED
907 ISCSI_CONFIG_VAR_ATTR,\r
908 BufferSize,\r
909 &Private->Current->AuthConfigData\r
910 );\r
e7fe4028 911 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;\r
083f7c69 912 break;\r
6a690e23 913\r
083f7c69 914 default:\r
083f7c69 915 break;\r
6a690e23 916 }\r
93e3992d 917 }\r
918\r
3a4e7a3e
ED
919 if (!EFI_ERROR (Status)) {\r
920 //\r
921 // Pass changed uncommitted data back to Form Browser\r
922 //\r
923 HiiSetBrowserData (&gIp4IScsiConfigGuid, mVendorStorageName, sizeof (ISCSI_CONFIG_IFR_NVDATA), (UINT8 *) IfrNvData, NULL);\r
924 }\r
925 \r
926 FreePool (IfrNvData);\r
927 \r
928 return Status;\r
6a690e23 929}\r
930\r
12618416 931/**\r
6a690e23 932 Updates the iSCSI configuration form to add/delete an entry for the iSCSI\r
933 device specified by the Controller.\r
934\r
669314e5 935 @param[in] DriverBindingHandle The driverbinding handle.\r
936 @param[in] Controller The controller handle of the iSCSI device.\r
937 @param[in] AddForm Whether to add or delete a form entry.\r
6a690e23 938\r
12618416 939 @retval EFI_SUCCESS The iSCSI configuration form is updated.\r
12618416 940 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
963dbb30 941 @retval Others Other errors as indicated.\r
12618416 942**/\r
943EFI_STATUS\r
944IScsiConfigUpdateForm (\r
945 IN EFI_HANDLE DriverBindingHandle,\r
946 IN EFI_HANDLE Controller,\r
947 IN BOOLEAN AddForm\r
948 )\r
6a690e23 949{\r
e48e37fc 950 LIST_ENTRY *Entry;\r
6a690e23 951 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
952 BOOLEAN EntryExisted;\r
6a690e23 953 EFI_STATUS Status;\r
779ae357 954 EFI_MAC_ADDRESS MacAddress;\r
955 UINTN HwAddressSize;\r
956 UINT16 VlanId;\r
6a690e23 957 CHAR16 PortString[128];\r
958 UINT16 FormIndex;\r
959 UINTN BufferSize;\r
7e3bcccb
LG
960 VOID *StartOpCodeHandle;\r
961 VOID *EndOpCodeHandle;\r
962 EFI_IFR_GUID_LABEL *StartLabel;\r
963 EFI_IFR_GUID_LABEL *EndLabel;\r
6a690e23 964\r
965 ConfigFormEntry = NULL;\r
966 EntryExisted = FALSE;\r
967\r
968 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
969 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
970\r
971 if (ConfigFormEntry->Controller == Controller) {\r
972 EntryExisted = TRUE;\r
973 break;\r
974 }\r
975 }\r
976\r
977 if (AddForm) {\r
978 if (EntryExisted) {\r
979 return EFI_SUCCESS;\r
980 } else {\r
981 //\r
982 // Add a new form.\r
983 //\r
e48e37fc 984 ConfigFormEntry = (ISCSI_CONFIG_FORM_ENTRY *) AllocateZeroPool (sizeof (ISCSI_CONFIG_FORM_ENTRY));\r
6a690e23 985 if (ConfigFormEntry == NULL) {\r
986 return EFI_OUT_OF_RESOURCES;\r
987 }\r
988\r
e48e37fc 989 InitializeListHead (&ConfigFormEntry->Link);\r
6a690e23 990 ConfigFormEntry->Controller = Controller;\r
991\r
992 //\r
779ae357 993 // Get the MAC address and convert it into the formatted string.\r
6a690e23 994 //\r
779ae357 995 Status = NetLibGetMacAddress (Controller, &MacAddress, &HwAddressSize);\r
6a690e23 996 ASSERT (Status == EFI_SUCCESS);\r
779ae357 997 VlanId = NetLibGetVlanId (Controller);\r
6a690e23 998\r
779ae357 999 IScsiMacAddrToStr (&MacAddress, (UINT32) HwAddressSize, VlanId, ConfigFormEntry->MacString);\r
6a690e23 1000\r
1001 //\r
1002 // Get the normal session configuration data.\r
1003 //\r
1004 BufferSize = sizeof (ConfigFormEntry->SessionConfigData);\r
1005 Status = gRT->GetVariable (\r
1006 ConfigFormEntry->MacString,\r
1007 &gEfiIScsiInitiatorNameProtocolGuid,\r
1008 NULL,\r
1009 &BufferSize,\r
1010 &ConfigFormEntry->SessionConfigData\r
1011 );\r
1012 if (EFI_ERROR (Status)) {\r
e48e37fc 1013 ZeroMem (&ConfigFormEntry->SessionConfigData, sizeof (ConfigFormEntry->SessionConfigData));\r
312e3bdf 1014 \r
1015 //\r
1016 // Generate OUI-format ISID based on MAC address.\r
1017 //\r
1018 CopyMem (ConfigFormEntry->SessionConfigData.IsId, &MacAddress, 6);\r
1019 ConfigFormEntry->SessionConfigData.IsId[0] = \r
b97a8d35 1020 (UINT8) (ConfigFormEntry->SessionConfigData.IsId[0] & 0x3F);\r
6a690e23 1021 }\r
1022 //\r
1023 // Get the CHAP authentication configuration data.\r
1024 //\r
1025 BufferSize = sizeof (ConfigFormEntry->AuthConfigData);\r
1026 Status = gRT->GetVariable (\r
1027 ConfigFormEntry->MacString,\r
c8ad2d7a 1028 &gIScsiCHAPAuthInfoGuid,\r
6a690e23 1029 NULL,\r
1030 &BufferSize,\r
1031 &ConfigFormEntry->AuthConfigData\r
1032 );\r
1033 if (EFI_ERROR (Status)) {\r
e48e37fc 1034 ZeroMem (&ConfigFormEntry->AuthConfigData, sizeof (ConfigFormEntry->AuthConfigData));\r
6a690e23 1035 }\r
1036 //\r
6c7a807a 1037 // Compose the Port string and create a new EFI_STRING_ID.\r
6a690e23 1038 //\r
dbcecd5d 1039 UnicodeSPrint (PortString, sizeof (PortString), L"Port %s", ConfigFormEntry->MacString);\r
cb7d01c0 1040 ConfigFormEntry->PortTitleToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, PortString, NULL);\r
6a690e23 1041\r
1042 //\r
6c7a807a 1043 // Compose the help string of this port and create a new EFI_STRING_ID.\r
6a690e23 1044 //\r
dbcecd5d 1045 UnicodeSPrint (PortString, sizeof (PortString), L"Set the iSCSI parameters on port %s", ConfigFormEntry->MacString);\r
cb7d01c0 1046 ConfigFormEntry->PortTitleHelpToken = HiiSetString (mCallbackInfo->RegisteredHandle, 0, PortString, NULL);\r
6a690e23 1047\r
e48e37fc 1048 InsertTailList (&mIScsiConfigFormList, &ConfigFormEntry->Link);\r
6a690e23 1049 mNumberOfIScsiDevices++;\r
1050 }\r
1051 } else {\r
1052 ASSERT (EntryExisted);\r
1053\r
1054 mNumberOfIScsiDevices--;\r
e48e37fc 1055 RemoveEntryList (&ConfigFormEntry->Link);\r
766c7483 1056 FreePool (ConfigFormEntry);\r
6a690e23 1057 }\r
1058 //\r
1059 // Allocate space for creation of Buffer\r
1060 //\r
7e3bcccb
LG
1061\r
1062 //\r
1063 // Init OpCode Handle\r
1064 //\r
1065 StartOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1066 ASSERT (StartOpCodeHandle != NULL);\r
1067\r
1068 EndOpCodeHandle = HiiAllocateOpCodeHandle ();\r
1069 ASSERT (EndOpCodeHandle != NULL);\r
1070\r
1071 //\r
1072 // Create Hii Extend Label OpCode as the start opcode\r
1073 //\r
1074 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1075 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1076 StartLabel->Number = DEVICE_ENTRY_LABEL;\r
1077\r
1078 //\r
1079 // Create Hii Extend Label OpCode as the end opcode\r
1080 //\r
1081 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL));\r
1082 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;\r
1083 EndLabel->Number = LABEL_END;\r
6a690e23 1084\r
93e3992d 1085 FormIndex = 0;\r
6a690e23 1086 NET_LIST_FOR_EACH (Entry, &mIScsiConfigFormList) {\r
1087 ConfigFormEntry = NET_LIST_USER_STRUCT (Entry, ISCSI_CONFIG_FORM_ENTRY, Link);\r
1088\r
7e3bcccb
LG
1089 HiiCreateGotoOpCode (\r
1090 StartOpCodeHandle, // Container for dynamic created opcodes\r
1091 FORMID_DEVICE_FORM, // Target Form ID\r
1092 ConfigFormEntry->PortTitleToken, // Prompt text\r
1093 ConfigFormEntry->PortTitleHelpToken, // Help text\r
1094 EFI_IFR_FLAG_CALLBACK, // Question flag\r
1095 (UINT16)(KEY_DEVICE_ENTRY_BASE + FormIndex) // Question ID\r
6a690e23 1096 );\r
1097\r
6a690e23 1098 FormIndex++;\r
1099 }\r
1100\r
7e3bcccb 1101 HiiUpdateForm (\r
93e3992d 1102 mCallbackInfo->RegisteredHandle,\r
c8ad2d7a 1103 &gIp4IScsiConfigGuid,\r
93e3992d 1104 FORMID_MAIN_FORM,\r
7e3bcccb
LG
1105 StartOpCodeHandle, // Label DEVICE_ENTRY_LABEL\r
1106 EndOpCodeHandle // LABEL_END\r
93e3992d 1107 );\r
1108\r
7e3bcccb
LG
1109 HiiFreeOpCodeHandle (StartOpCodeHandle);\r
1110 HiiFreeOpCodeHandle (EndOpCodeHandle);\r
6a690e23 1111\r
1112 return EFI_SUCCESS;\r
1113}\r
1114\r
12618416 1115/**\r
6a690e23 1116 Initialize the iSCSI configuration form.\r
1117\r
669314e5 1118 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
6a690e23 1119\r
669314e5 1120 @retval EFI_SUCCESS The iSCSI configuration form is initialized.\r
1121 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
963dbb30 1122 @retval Others Other errors as indicated.\r
12618416 1123**/\r
1124EFI_STATUS\r
1125IScsiConfigFormInit (\r
963dbb30 1126 VOID\r
12618416 1127 )\r
6a690e23 1128{\r
93e3992d 1129 EFI_STATUS Status;\r
1130 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
93e3992d 1131 ISCSI_FORM_CALLBACK_INFO *CallbackInfo;\r
1132\r
69b0882d 1133 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **)&HiiDatabase);\r
6a690e23 1134 if (EFI_ERROR (Status)) {\r
93e3992d 1135 return Status;\r
6a690e23 1136 }\r
1137\r
f6f910dd 1138 CallbackInfo = (ISCSI_FORM_CALLBACK_INFO *) AllocateZeroPool (sizeof (ISCSI_FORM_CALLBACK_INFO));\r
6a690e23 1139 if (CallbackInfo == NULL) {\r
1140 return EFI_OUT_OF_RESOURCES;\r
1141 }\r
1142\r
f2a94e25 1143 CallbackInfo->Signature = ISCSI_FORM_CALLBACK_INFO_SIGNATURE;\r
93e3992d 1144 CallbackInfo->HiiDatabase = HiiDatabase;\r
f2a94e25 1145 CallbackInfo->Current = NULL;\r
6a690e23 1146\r
93e3992d 1147 CallbackInfo->ConfigAccess.ExtractConfig = IScsiFormExtractConfig;\r
1148 CallbackInfo->ConfigAccess.RouteConfig = IScsiFormRouteConfig;\r
1149 CallbackInfo->ConfigAccess.Callback = IScsiFormCallback;\r
6a690e23 1150\r
69b0882d 1151 Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **)&CallbackInfo->ConfigRouting);\r
93e3992d 1152 if (EFI_ERROR (Status)) {\r
f2a94e25 1153 FreePool(CallbackInfo);\r
93e3992d 1154 return Status;\r
1155 }\r
1156\r
1157 //\r
f6f910dd 1158 // Install Device Path Protocol and Config Access protocol to driver handle\r
93e3992d 1159 //\r
f6f910dd 1160 Status = gBS->InstallMultipleProtocolInterfaces (\r
93e3992d 1161 &CallbackInfo->DriverHandle,\r
f6f910dd 1162 &gEfiDevicePathProtocolGuid,\r
1163 &mIScsiHiiVendorDevicePath,\r
93e3992d 1164 &gEfiHiiConfigAccessProtocolGuid,\r
f6f910dd 1165 &CallbackInfo->ConfigAccess,\r
1166 NULL\r
6a690e23 1167 );\r
6a690e23 1168 ASSERT_EFI_ERROR (Status);\r
93e3992d 1169 \r
6a690e23 1170 //\r
93e3992d 1171 // Publish our HII data\r
6a690e23 1172 //\r
cb7d01c0 1173 CallbackInfo->RegisteredHandle = HiiAddPackages (\r
c8ad2d7a 1174 &gIp4IScsiConfigGuid,\r
cb7d01c0 1175 CallbackInfo->DriverHandle,\r
ace28761 1176 IScsi4DxeStrings,\r
cb7d01c0 1177 IScsiConfigDxeBin,\r
1178 NULL\r
1179 );\r
1180 if (CallbackInfo->RegisteredHandle == NULL) {\r
f2a94e25 1181 FreePool(CallbackInfo);\r
cb7d01c0 1182 return EFI_OUT_OF_RESOURCES;\r
6a690e23 1183 }\r
1184\r
93e3992d 1185 mCallbackInfo = CallbackInfo;\r
6a690e23 1186\r
1187 return Status;\r
1188}\r
1189\r
12618416 1190/**\r
6a690e23 1191 Unload the iSCSI configuration form, this includes: delete all the iSCSI\r
1192 device configuration entries, uninstall the form callback protocol and\r
1193 free the resources used.\r
1194\r
669314e5 1195 @param[in] DriverBindingHandle The iSCSI driverbinding handle.\r
1196 \r
12618416 1197 @retval EFI_SUCCESS The iSCSI configuration form is unloaded.\r
12618416 1198 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
12618416 1199**/\r
1200EFI_STATUS\r
1201IScsiConfigFormUnload (\r
1202 IN EFI_HANDLE DriverBindingHandle\r
1203 )\r
6a690e23 1204{\r
1205 ISCSI_CONFIG_FORM_ENTRY *ConfigFormEntry;\r
6a690e23 1206\r
e48e37fc 1207 while (!IsListEmpty (&mIScsiConfigFormList)) {\r
6a690e23 1208 //\r
1209 // Uninstall the device forms as the iSCSI driver instance may fail to\r
1210 // control the controller but still install the device configuration form.\r
1211 // In such case, upon driver unloading, the driver instance's driverbinding.\r
1212 // stop () won't be called, so we have to take this chance here to uninstall\r
1213 // the device form.\r
1214 //\r
1215 ConfigFormEntry = NET_LIST_USER_STRUCT (mIScsiConfigFormList.ForwardLink, ISCSI_CONFIG_FORM_ENTRY, Link);\r
1216 IScsiConfigUpdateForm (DriverBindingHandle, ConfigFormEntry->Controller, FALSE);\r
1217 }\r
1218\r
6a690e23 1219 //\r
93e3992d 1220 // Remove HII package list\r
6a690e23 1221 //\r
93e3992d 1222 mCallbackInfo->HiiDatabase->RemovePackageList (\r
1223 mCallbackInfo->HiiDatabase,\r
1224 mCallbackInfo->RegisteredHandle\r
1225 );\r
6a690e23 1226\r
1227 //\r
93e3992d 1228 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
6a690e23 1229 //\r
f6f910dd 1230 gBS->UninstallMultipleProtocolInterfaces (\r
1231 mCallbackInfo->DriverHandle,\r
1232 &gEfiDevicePathProtocolGuid,\r
1233 &mIScsiHiiVendorDevicePath,\r
1234 &gEfiHiiConfigAccessProtocolGuid,\r
1235 &mCallbackInfo->ConfigAccess,\r
1236 NULL\r
1237 );\r
766c7483 1238 FreePool (mCallbackInfo);\r
6a690e23 1239\r
1240 return EFI_SUCCESS;\r
1241}\r